Compare commits

...

4 Commits

181 changed files with 1774 additions and 1678 deletions

View 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

View File

@@ -8,11 +8,10 @@
import shlex import shlex
import subprocess import subprocess
import sys import sys
from typing import List, Optional, Union
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.path import Path, format_os_path, path_to_os_path, system_path_filter
import spack.error
from spack.util.path import Path, format_os_path, path_to_os_path, system_path_filter
__all__ = ["Executable", "which", "ProcessError"] __all__ = ["Executable", "which", "ProcessError"]
@@ -27,13 +26,20 @@ def __init__(self, name):
# filter back to platform dependent path # filter back to platform dependent path
self.exe = path_to_os_path(*self.exe) self.exe = path_to_os_path(*self.exe)
self.default_env = {} self.default_env = {}
from spack.util.environment import EnvironmentModifications # no cycle self._default_envmod = None
self.default_envmod = EnvironmentModifications()
self.returncode = None self.returncode = None
if not self.exe: 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 @system_path_filter
def add_default_arg(self, arg): 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. By default, the subprocess inherits the parent's file descriptors.
""" """
from llnl.util.envmod import EnvironmentModifications
# Environment # Environment
env_arg = kwargs.get("env", None) env_arg = kwargs.get("env", None)
@@ -130,8 +138,6 @@ def __call__(self, *args, **kwargs):
self.default_envmod.apply_modifications(env) self.default_envmod.apply_modifications(env)
env.update(self.default_env) env.update(self.default_env)
from spack.util.environment import EnvironmentModifications # no cycle
# Apply env argument # Apply env argument
if isinstance(env_arg, EnvironmentModifications): if isinstance(env_arg, EnvironmentModifications):
env_arg.apply_modifications(env) env_arg.apply_modifications(env)
@@ -227,27 +233,26 @@ def streamify(arg, mode):
rc = self.returncode = proc.returncode rc = self.returncode = proc.returncode
if fail_on_error and rc != 0 and (rc not in ignore_errors): 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 result:
# If the output is not captured in the result, it will have # If the output is not captured in the result, it will have
# been stored either in the specified files (e.g. if # been stored either in the specified files (e.g. if
# 'output' specifies a file) or written to the parent's # 'output' specifies a file) or written to the parent's
# stdout/stderr (e.g. if 'output' is not specified) # 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 return result
except OSError as e: 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: except subprocess.CalledProcessError as e:
if fail_on_error: if fail_on_error:
raise ProcessError( raise ProcessError(
str(e), f"{str(e)}\n"
"\nExit status %d when invoking command: %s" f" Exit status {proc.returncode} when invoking command: '{cmd_line_string}'"
% (proc.returncode, cmd_line_string),
) )
finally: finally:
@@ -275,16 +280,31 @@ def __str__(self):
@system_path_filter @system_path_filter
def which_string(*args, **kwargs): def which_string(*args: str, path: Optional[Union[List[str], str]] = None, required: bool = False):
"""Like ``which()``, but return a string instead of an ``Executable``.""" """Finds an executable in the path like command-line which.
path = kwargs.get("path", os.environ.get("PATH", ""))
required = kwargs.get("required", False) 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): if isinstance(path, str):
path = path.split(os.pathsep) path = path.split(os.pathsep)
for name in args: for name in args:
win_candidates = [] win_candidates: List[str] = []
if sys.platform == "win32" and (not name.endswith(".exe") and not name.endswith(".bat")): if sys.platform == "win32" and (not name.endswith(".exe") and not name.endswith(".bat")):
win_candidates = [name + ext for ext in [".exe", ".bat"]] win_candidates = [name + ext for ext in [".exe", ".bat"]]
candidate_names = [name] if not win_candidates else win_candidates candidate_names = [name] if not win_candidates else win_candidates
@@ -309,19 +329,19 @@ def which_string(*args, **kwargs):
return exe return exe
if required: if required:
raise CommandNotFoundError("spack requires '%s'. Make sure it is in your path." % args[0]) raise CommandNotFoundError(args[0])
return None 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. """Finds an executable in the path like command-line which.
If given multiple executables, returns the first one that is found. If given multiple executables, returns the first one that is found.
If no executables are found, returns None. If no executables are found, returns None.
Parameters: Parameters:
*args (str): One or more executables to search for *args: One or more executables to search for
Keyword Arguments: Keyword Arguments:
path (list or str): The path to search. Defaults to ``PATH`` path (list or str): The path to search. Defaults to ``PATH``
@@ -330,13 +350,17 @@ def which(*args, **kwargs):
Returns: Returns:
Executable: The first executable that is found in the path 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 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.""" """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.""" """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

View File

@@ -19,12 +19,11 @@
from sys import platform as _platform from sys import platform as _platform
from llnl.util import tty from llnl.util import tty
from llnl.util.executable import CommandNotFoundError, Executable, which
from llnl.util.lang import dedupe, memoized 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 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" is_windows = _platform == "win32"
if not is_windows: if not is_windows:

View File

@@ -10,11 +10,10 @@
import time import time
from datetime import datetime from datetime import datetime
import llnl.util.string
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.lang import pretty_seconds from llnl.util.lang import pretty_seconds
import spack.util.string
if sys.platform != "win32": if sys.platform != "win32":
import fcntl import fcntl
@@ -165,7 +164,7 @@ def _attempts_str(wait_time, nattempts):
if nattempts <= 1: if nattempts <= 1:
return "" return ""
attempts = spack.util.string.plural(nattempts, "attempt") attempts = llnl.util.string.plural(nattempts, "attempt")
return " after {} and {}".format(pretty_seconds(wait_time), attempts) return " after {} and {}".format(pretty_seconds(wait_time), attempts)

159
lib/spack/llnl/util/path.py Normal file
View 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)

View File

@@ -24,8 +24,7 @@
import traceback import traceback
import llnl.util.tty.log as log import llnl.util.tty.log as log
from llnl.util.executable import which
from spack.util.executable import which
termios = None termios = None
try: try:

View File

@@ -5,12 +5,12 @@
import os import os
from llnl.util.executable import Executable, ProcessError
from llnl.util.lang import memoized from llnl.util.lang import memoized
import spack.spec import spack.spec
from spack.compilers.clang import Clang from spack.compilers.clang import Clang
from spack.spec import CompilerSpec from spack.spec import CompilerSpec
from spack.util.executable import Executable, ProcessError
class ABI(object): class ABI(object):

View File

@@ -28,6 +28,7 @@
import llnl.util.filesystem as fsys import llnl.util.filesystem as fsys
import llnl.util.lang import llnl.util.lang
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import which
from llnl.util.filesystem import BaseDirectoryVisitor, mkdirp, visit_directory_tree from llnl.util.filesystem import BaseDirectoryVisitor, mkdirp, visit_directory_tree
import spack.cmd import spack.cmd
@@ -42,6 +43,7 @@
import spack.store import spack.store
import spack.util.file_cache as file_cache import spack.util.file_cache as file_cache
import spack.util.gpg import spack.util.gpg
import spack.util.path
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
import spack.util.url as url_util import spack.util.url as url_util
@@ -50,7 +52,6 @@
from spack.relocate import utf8_paths_to_single_binary_regex from spack.relocate import utf8_paths_to_single_binary_regex
from spack.spec import Spec from spack.spec import Spec
from spack.stage import Stage from spack.stage import Stage
from spack.util.executable import which
_build_cache_relative_path = "build_cache" _build_cache_relative_path = "build_cache"
_build_cache_keys_relative_path = "_pgp" _build_cache_keys_relative_path = "_pgp"

View File

@@ -12,12 +12,12 @@
import archspec.cpu import archspec.cpu
import llnl.util.envmod
import llnl.util.executable
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
from llnl.util import tty from llnl.util import tty
import spack.store import spack.store
import spack.util.environment
import spack.util.executable
from .config import spec_for_current_python from .config import spec_for_current_python
@@ -186,11 +186,11 @@ def _executables_in_store(executables, query_spec, query_info=None):
if ( if (
os.path.exists(bin_dir) os.path.exists(bin_dir)
and os.path.isdir(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: 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 query_info["spec"] = concrete_spec
return True return True
return False return False

View File

@@ -31,6 +31,8 @@
import uuid import uuid
from typing import Callable, List, Optional from typing import Callable, List, Optional
import llnl.util.envmod
import llnl.util.executable
from llnl.util import tty from llnl.util import tty
from llnl.util.lang import GroupedExceptionHandler from llnl.util.lang import GroupedExceptionHandler
@@ -46,8 +48,6 @@
import spack.spec import spack.spec
import spack.store import spack.store
import spack.user_environment import spack.user_environment
import spack.util.environment
import spack.util.executable
import spack.util.path import spack.util.path
import spack.util.spack_yaml import spack.util.spack_yaml
import spack.util.url 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( def ensure_executables_in_path_or_raise(
executables: list, executables: list,
abstract_spec: str, 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. """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. in order. The function exits on the first one found.
abstract_spec (str): abstract spec that provides the executables abstract_spec (str): abstract spec that provides the executables
cmd_check (object): callable predicate that takes a 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. ``True`` if the executable is acceptable, ``False`` otherwise.
Can be used to, e.g., ensure a suitable version of the command before Can be used to, e.g., ensure a suitable version of the command before
accepting for bootstrapping. accepting for bootstrapping.
@@ -420,7 +420,7 @@ def ensure_executables_in_path_or_raise(
Executable object Executable object
""" """
cmd = spack.util.executable.which(*executables) cmd = llnl.util.executable.which(*executables)
if cmd: if cmd:
if not cmd_check or cmd_check(cmd): if not cmd_check or cmd_check(cmd):
return cmd return cmd
@@ -439,7 +439,7 @@ def ensure_executables_in_path_or_raise(
current_bootstrapper.last_search["spec"], current_bootstrapper.last_search["spec"],
current_bootstrapper.last_search["command"], current_bootstrapper.last_search["command"],
) )
env_mods = spack.util.environment.EnvironmentModifications() env_mods = llnl.util.envmod.EnvironmentModifications()
for dep in concrete_spec.traverse( for dep in concrete_spec.traverse(
root=True, order="post", deptype=("link", "run") root=True, order="post", deptype=("link", "run")
): ):
@@ -514,7 +514,7 @@ def verify_patchelf(patchelf):
Arguments: 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() out = patchelf("--version", output=str, error=os.devnull, fail_on_error=False).strip()
if patchelf.returncode != 0: if patchelf.returncode != 0:

View File

@@ -12,12 +12,12 @@
import archspec.cpu import archspec.cpu
import llnl.util.executable
from llnl.util import tty from llnl.util import tty
import spack.build_environment import spack.build_environment
import spack.environment import spack.environment
import spack.tengine import spack.tengine
import spack.util.executable
from ._common import _root_spec from ._common import _root_spec
from .config import root_path, spec_for_current_python, store_path 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): def _install_with_depfile(self):
spackcmd = spack.util.executable.which("spack") spackcmd = llnl.util.executable.which("spack")
spackcmd( spackcmd(
"-e", "-e",
str(self.environment_root()), str(self.environment_root()),
@@ -129,7 +129,7 @@ def _install_with_depfile(self):
"-o", "-o",
str(self.environment_root().joinpath("Makefile")), str(self.environment_root().joinpath("Makefile")),
) )
make = spack.util.executable.which("make") make = llnl.util.executable.which("make")
kwargs = {} kwargs = {}
if not tty.is_debug(): if not tty.is_debug():
kwargs = {"output": os.devnull, "error": os.devnull} kwargs = {"output": os.devnull, "error": os.devnull}

View File

@@ -5,7 +5,7 @@
"""Query the status of bootstrapping on this machine""" """Query the status of bootstrapping on this machine"""
import platform import platform
import spack.util.executable import llnl.util.executable
from ._common import _executables_in_store, _python_import, _try_import_from_store from ._common import _executables_in_store, _python_import, _try_import_from_store
from .config import ensure_bootstrap_configuration 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.""" """Search for an executable is the system path only."""
if isinstance(exes, str): if isinstance(exes, str):
exes = (exes,) exes = (exes,)
if spack.util.executable.which_string(*exes): if llnl.util.executable.which_string(*exes):
return True, None return True, None
return False, msg 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.""" """Search for an executable in the system path or in the bootstrap store."""
if isinstance(exes, str): if isinstance(exes, str):
exes = (exes,) 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 True, None
return False, msg return False, msg

View File

@@ -43,7 +43,19 @@
from typing import List, Tuple from typing import List, Tuple
import llnl.util.tty as tty 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.lang import dedupe
from llnl.util.string import plural
from llnl.util.symlink import symlink from llnl.util.symlink import symlink
from llnl.util.tty.color import cescape, colorize from llnl.util.tty.color import cescape, colorize
from llnl.util.tty.log import MultiProcessFd from llnl.util.tty.log import MultiProcessFd
@@ -63,25 +75,12 @@
import spack.store import spack.store
import spack.subprocess_context import spack.subprocess_context
import spack.user_environment import spack.user_environment
import spack.util.path
import spack.util.pattern import spack.util.pattern
from spack.error import NoHeadersError, NoLibrariesError from spack.error import NoHeadersError, NoLibrariesError
from spack.installer import InstallError from spack.installer import InstallError
from spack.util.cpus import cpus_available 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.log_parse import make_log_context, parse_log_events
from spack.util.module_cmd import load_module, module, path_from_modules 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. # 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 # List of errors considered "build errors", for which we'll show log
# context instead of Python context. # 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): def __init__(self, msg, module, classname, traceback_string, log_name, log_type, context):
super(ChildError, self).__init__(msg) super(ChildError, self).__init__(msg)

View File

@@ -2,11 +2,11 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details. # Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import llnl.util.executable
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import spack.directives import spack.directives
import spack.package_base import spack.package_base
import spack.util.executable
from .autotools import AutotoolsBuilder, AutotoolsPackage from .autotools import AutotoolsBuilder, AutotoolsPackage
@@ -22,7 +22,7 @@ def configure(self, pkg, spec, prefix):
prezip = spec["aspell"].prefix.bin.prezip prezip = spec["aspell"].prefix.bin.prezip
destdir = prefix destdir = prefix
sh = spack.util.executable.which("sh") sh = llnl.util.executable.which("sh")
sh( sh(
"./configure", "./configure",
"--vars", "--vars",

View File

@@ -11,6 +11,7 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import Executable
import spack.build_environment import spack.build_environment
import spack.builder import spack.builder
@@ -18,7 +19,6 @@
from spack.directives import build_system, conflicts, depends_on from spack.directives import build_system, conflicts, depends_on
from spack.multimethod import when from spack.multimethod import when
from spack.operating_systems.mac_os import macos_version from spack.operating_systems.mac_os import macos_version
from spack.util.executable import Executable
from spack.version import Version from spack.version import Version
from ._checks import ( from ._checks import (

View File

@@ -15,7 +15,6 @@
import spack.build_environment import spack.build_environment
import spack.builder import spack.builder
import spack.package_base import spack.package_base
import spack.util.path
from spack.directives import build_system, depends_on, variant from spack.directives import build_system, depends_on, variant
from spack.multimethod import when from spack.multimethod import when

View File

@@ -11,6 +11,8 @@
import xml.etree.ElementTree as ElementTree import xml.etree.ElementTree as ElementTree
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.envmod import EnvironmentModifications
from llnl.util.executable import Executable
from llnl.util.filesystem import ( from llnl.util.filesystem import (
HeaderList, HeaderList,
LibraryList, LibraryList,
@@ -25,8 +27,6 @@
import spack.error import spack.error
from spack.build_environment import dso_suffix from spack.build_environment import dso_suffix
from spack.package_base import InstallError 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.util.prefix import Prefix
from spack.version import Version, ver from spack.version import Version, ver

View File

@@ -4,11 +4,11 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os import os
import llnl.util.executable
from llnl.util.filesystem import find from llnl.util.filesystem import find
import spack.builder import spack.builder
import spack.package_base import spack.package_base
import spack.util.executable
from spack.directives import build_system, depends_on, extends from spack.directives import build_system, depends_on, extends
from spack.multimethod import when from spack.multimethod import when
@@ -41,11 +41,11 @@ class LuaPackage(spack.package_base.PackageBase):
@property @property
def lua(self): 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 @property
def luarocks(self): 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 return lr

View File

@@ -3,12 +3,12 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
from llnl.util.executable import which
import spack.builder import spack.builder
import spack.package_base import spack.package_base
from spack.directives import build_system, depends_on from spack.directives import build_system, depends_on
from spack.multimethod import when from spack.multimethod import when
from spack.util.executable import which
from ._checks import BaseBuilder from ._checks import BaseBuilder

View File

@@ -8,11 +8,11 @@
import shutil import shutil
from os.path import basename, dirname, isdir 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 llnl.util.filesystem import find_headers, find_libraries, join_path
from spack.directives import conflicts, variant from spack.directives import conflicts, variant
from spack.util.environment import EnvironmentModifications
from spack.util.executable import Executable
from .generic import Package from .generic import Package

View File

@@ -5,13 +5,13 @@
import inspect import inspect
import os import os
from llnl.util.executable import Executable
from llnl.util.filesystem import filter_file from llnl.util.filesystem import filter_file
import spack.builder import spack.builder
import spack.package_base import spack.package_base
from spack.directives import build_system, extends from spack.directives import build_system, extends
from spack.package_base import PackageBase from spack.package_base import PackageBase
from spack.util.executable import Executable
from ._checks import BaseBuilder, execute_build_time_tests from ._checks import BaseBuilder, execute_build_time_tests

View File

@@ -8,13 +8,13 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.lang as lang import llnl.util.lang as lang
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.envmod import env_flag
from llnl.util.executable import Executable, ProcessError
import spack.builder import spack.builder
from spack.build_environment import SPACK_NO_PARALLEL_MAKE, determine_number_of_jobs from spack.build_environment import SPACK_NO_PARALLEL_MAKE, determine_number_of_jobs
from spack.directives import build_system, extends from spack.directives import build_system, extends
from spack.package_base import PackageBase from spack.package_base import PackageBase
from spack.util.environment import env_flag
from spack.util.executable import Executable, ProcessError
class RacketPackage(PackageBase): class RacketPackage(PackageBase):

View File

@@ -518,7 +518,7 @@ def setup_build_environment(self, env):
Spack's store. Spack's store.
Args: Args:
env (spack.util.environment.EnvironmentModifications): environment env (llnl.util.envmod.EnvironmentModifications): environment
modifications to be applied when the package is built. Package authors modifications to be applied when the package is built. Package authors
can call methods on it to alter the build environment. can call methods on it to alter the build environment.
""" """
@@ -546,7 +546,7 @@ def setup_dependent_build_environment(self, env, dependent_spec):
variable. variable.
Args: Args:
env (spack.util.environment.EnvironmentModifications): environment env (llnl.util.envmod.EnvironmentModifications): environment
modifications to be applied when the dependent package is built. modifications to be applied when the dependent package is built.
Package authors can call methods on it to alter the build environment. Package authors can call methods on it to alter the build environment.

View File

@@ -16,6 +16,7 @@
import ruamel.yaml as yaml import ruamel.yaml as yaml
from ruamel.yaml.error import MarkedYAMLError from ruamel.yaml.error import MarkedYAMLError
import llnl.util.string
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import join_path from llnl.util.filesystem import join_path
from llnl.util.lang import attr_setdefault, index_by from llnl.util.lang import attr_setdefault, index_by
@@ -33,7 +34,6 @@
import spack.traverse as traverse import spack.traverse as traverse
import spack.user_environment as uenv import spack.user_environment as uenv
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
import spack.util.string
# cmd has a submodule called "list" so preserve the python list module # cmd has a submodule called "list" so preserve the python list module
python_list = list 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 category, e.g. if pkg_type is "installed" then the message
would be "3 installed packages" 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(): def spack_is_git_repo():

View File

@@ -11,6 +11,7 @@
import urllib.parse import urllib.parse
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.string import plural
import spack.binary_distribution as bindist import spack.binary_distribution as bindist
import spack.cmd import spack.cmd
@@ -30,7 +31,6 @@
from spack.error import SpecError from spack.error import SpecError
from spack.spec import Spec, save_dependency_specfiles from spack.spec import Spec, save_dependency_specfiles
from spack.stage import Stage from spack.stage import Stage
from spack.util.string import plural
description = "create, download and install binary packages" description = "create, download and install binary packages"
section = "packaging" section = "packaging"

View File

@@ -6,11 +6,11 @@
import os import os
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import ProcessError
from llnl.util.filesystem import mkdirp, working_dir from llnl.util.filesystem import mkdirp, working_dir
import spack.paths import spack.paths
import spack.util.git import spack.util.git
from spack.util.executable import ProcessError
_SPACK_UPSTREAM = "https://github.com/spack/spack" _SPACK_UPSTREAM = "https://github.com/spack/spack"

View File

@@ -10,6 +10,7 @@
import urllib.parse import urllib.parse
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import ProcessError, which
from llnl.util.filesystem import mkdirp from llnl.util.filesystem import mkdirp
import spack.repo import spack.repo
@@ -23,7 +24,6 @@
parse_version, parse_version,
) )
from spack.util.editor import editor from spack.util.editor import editor
from spack.util.executable import ProcessError, which
from spack.util.naming import ( from spack.util.naming import (
mod_to_class, mod_to_class,
simplify_name, simplify_name,

View File

@@ -12,6 +12,7 @@
from glob import glob from glob import glob
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import which
from llnl.util.filesystem import working_dir from llnl.util.filesystem import working_dir
import spack.config import spack.config
@@ -19,7 +20,6 @@
import spack.platforms import spack.platforms
import spack.util.git import spack.util.git
from spack.main import get_version from spack.main import get_version
from spack.util.executable import which
description = "debugging commands for troubleshooting Spack" description = "debugging commands for troubleshooting Spack"
section = "developer" section = "developer"

View File

@@ -13,7 +13,6 @@
import spack.cmd.common.arguments as arguments import spack.cmd.common.arguments as arguments
import spack.environment as ev import spack.environment as ev
import spack.solver.asp as asp import spack.solver.asp as asp
import spack.util.environment
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
description = "compare two specs" description = "compare two specs"

View File

@@ -11,7 +11,9 @@
import tempfile import tempfile
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.string as string
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.envmod import EnvironmentModifications
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
from llnl.util.tty.color import colorize from llnl.util.tty.color import colorize
@@ -28,8 +30,6 @@
import spack.schema.env import spack.schema.env
import spack.tengine import spack.tengine
import spack.traverse as traverse import spack.traverse as traverse
import spack.util.string as string
from spack.util.environment import EnvironmentModifications
description = "manage virtual environments" description = "manage virtual environments"
section = "environments" section = "environments"

View File

@@ -18,7 +18,6 @@
import spack.cray_manifest as cray_manifest import spack.cray_manifest as cray_manifest
import spack.detection import spack.detection
import spack.error import spack.error
import spack.util.environment
description = "manage external packages in Spack configuration" description = "manage external packages in Spack configuration"
section = "config" section = "config"

View File

@@ -5,13 +5,14 @@
import sys import sys
import llnl.util.envmod
import spack.cmd import spack.cmd
import spack.cmd.common.arguments as arguments import spack.cmd.common.arguments as arguments
import spack.cmd.find import spack.cmd.find
import spack.environment as ev import spack.environment as ev
import spack.store import spack.store
import spack.user_environment as uenv import spack.user_environment as uenv
import spack.util.environment
description = "add package to the user environment" description = "add package to the user environment"
section = "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") 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: for spec in specs:
env_mod.extend(uenv.environment_modifications_for_spec(spec)) env_mod.extend(uenv.environment_modifications_for_spec(spec))
env_mod.prepend_path(uenv.spack_loaded_hashes_var, spec.dag_hash()) env_mod.prepend_path(uenv.spack_loaded_hashes_var, spec.dag_hash())

View File

@@ -6,10 +6,11 @@
import posixpath import posixpath
import sys import sys
import llnl.util.executable
from llnl.util.path import convert_to_posix_path
import spack.paths import spack.paths
import spack.util.executable
from spack.spec import Spec from spack.spec import Spec
from spack.util.path import convert_to_posix_path
description = "generate Windows installer" description = "generate Windows installer"
section = "admin" section = "admin"
@@ -100,7 +101,7 @@ def make_installer(parser, args):
spack_logo = posixpath.join(posix_root, "share/spack/logo/favicon.ico") spack_logo = posixpath.join(posix_root, "share/spack/logo/favicon.ico")
try: try:
spack.util.executable.Executable(cmake_path)( llnl.util.executable.Executable(cmake_path)(
"-S", "-S",
source_dir, source_dir,
"-B", "-B",
@@ -111,30 +112,30 @@ def make_installer(parser, args):
"-DSPACK_LOGO=%s" % spack_logo, "-DSPACK_LOGO=%s" % spack_logo,
"-DSPACK_GIT_VERBOSITY=%s" % git_verbosity, "-DSPACK_GIT_VERBOSITY=%s" % git_verbosity,
) )
except spack.util.executable.ProcessError: except llnl.util.executable.ProcessError:
print("Failed to generate installer") print("Failed to generate installer")
return spack.util.executable.ProcessError.returncode return llnl.util.executable.ProcessError.returncode
try: try:
spack.util.executable.Executable(cpack_path)( llnl.util.executable.Executable(cpack_path)(
"--config", "%s/CPackConfig.cmake" % output_dir, "-B", "%s/" % output_dir "--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") print("Failed to generate installer")
return spack.util.executable.ProcessError.returncode return llnl.util.executable.ProcessError.returncode
try: try:
spack.util.executable.Executable(os.environ.get("WIX") + "/bin/candle.exe")( llnl.util.executable.Executable(os.environ.get("WIX") + "/bin/candle.exe")(
"-ext", "-ext",
"WixBalExtension", "WixBalExtension",
"%s/bundle.wxs" % output_dir, "%s/bundle.wxs" % output_dir,
"-out", "-out",
"%s/bundle.wixobj" % output_dir, "%s/bundle.wixobj" % output_dir,
) )
except spack.util.executable.ProcessError: except llnl.util.executable.ProcessError:
print("Failed to generate installer chain") print("Failed to generate installer chain")
return spack.util.executable.ProcessError.returncode return llnl.util.executable.ProcessError.returncode
try: try:
spack.util.executable.Executable(os.environ.get("WIX") + "/bin/light.exe")( llnl.util.executable.Executable(os.environ.get("WIX") + "/bin/light.exe")(
"-sw1134", "-sw1134",
"-ext", "-ext",
"WixBalExtension", "WixBalExtension",
@@ -142,9 +143,9 @@ def make_installer(parser, args):
"-out", "-out",
"%s/Spack.exe" % output_dir, "%s/Spack.exe" % output_dir,
) )
except spack.util.executable.ProcessError: except llnl.util.executable.ProcessError:
print("Failed to generate installer chain") 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)) print("Successfully generated Spack.exe in %s" % (output_dir))
else: else:
print("The make-installer command is currently only supported on Windows.") print("The make-installer command is currently only supported on Windows.")

View File

@@ -10,6 +10,7 @@
import os import os
import sys import sys
import llnl.util.executable as exe
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
@@ -17,7 +18,6 @@
import spack.cmd.common.arguments as arguments import spack.cmd.common.arguments as arguments
import spack.paths import spack.paths
import spack.repo import spack.repo
import spack.util.executable as exe
import spack.util.package_hash as ph import spack.util.package_hash as ph
description = "query packages associated with particular git revisions" description = "query packages associated with particular git revisions"

View File

@@ -10,11 +10,11 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import llnl.util.tty.color as color import llnl.util.tty.color as color
from llnl.util.executable import which
from llnl.util.filesystem import working_dir from llnl.util.filesystem import working_dir
import spack.paths import spack.paths
import spack.util.git import spack.util.git
from spack.util.executable import which
description = "runs source code style checks on spack" description = "runs source code style checks on spack"
section = "developer" section = "developer"

View File

@@ -5,6 +5,7 @@
import io import io
import sys import sys
import llnl.util.string
import llnl.util.tty as tty import llnl.util.tty as tty
import llnl.util.tty.colify as colify import llnl.util.tty.colify as colify
@@ -24,7 +25,7 @@ def report_tags(category, tags):
if isatty: if isatty:
num = len(tags) num = len(tags)
fmt = "{0} package tag".format(category) 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: if tags:
colify.colify(tags, output=buffer, tty=isatty, indent=4) colify.colify(tags, output=buffer, tty=isatty, indent=4)

View File

@@ -6,11 +6,12 @@
import os import os
import sys import sys
import llnl.util.envmod
import spack.cmd import spack.cmd
import spack.cmd.common.arguments as arguments import spack.cmd.common.arguments as arguments
import spack.error import spack.error
import spack.user_environment as uenv import spack.user_environment as uenv
import spack.util.environment
description = "remove package from the user environment" description = "remove package from the user environment"
section = "user environment" section = "user environment"
@@ -82,7 +83,7 @@ def unload(parser, args):
) )
return 1 return 1
env_mod = spack.util.environment.EnvironmentModifications() env_mod = llnl.util.envmod.EnvironmentModifications()
for spec in specs: for spec in specs:
env_mod.extend(uenv.environment_modifications_for_spec(spec).reversed()) env_mod.extend(uenv.environment_modifications_for_spec(spec).reversed())
env_mod.remove_path(uenv.spack_loaded_hashes_var, spec.dag_hash()) env_mod.remove_path(uenv.spack_loaded_hashes_var, spec.dag_hash())

View File

@@ -13,18 +13,18 @@
import tempfile import tempfile
from typing import List, Optional, Sequence from typing import List, Optional, Sequence
import llnl.util.envmod as envmod
import llnl.util.executable
import llnl.util.lang import llnl.util.lang
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import path_contains_subdirectory, paths_containing_libs from llnl.util.filesystem import path_contains_subdirectory, paths_containing_libs
from llnl.util.path import system_path_filter
import spack.compilers import spack.compilers
import spack.error import spack.error
import spack.spec import spack.spec
import spack.util.executable
import spack.util.module_cmd import spack.util.module_cmd
import spack.version import spack.version
from spack.util.environment import filter_system_paths
from spack.util.path import system_path_filter
__all__ = ["Compiler"] __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 compiler_path (path): path of the compiler to be invoked
version_arg (str): the argument used to extract version information 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: if version_arg:
output = compiler(version_arg, output=str, error=str, ignore_errors=ignore_errors) output = compiler(version_arg, output=str, error=str, ignore_errors=ignore_errors)
else: 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 # not just executable name. If we don't do this, and the path changes
# (e.g., during testing), we can get incorrect results. # (e.g., during testing), we can get incorrect results.
if not os.path.isabs(compiler_path): 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) 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 # system paths. Note that 'filter_system_paths' only checks for an
# exact match, while 'in_system_subdirectory' checks if a path contains # exact match, while 'in_system_subdirectory' checks if a path contains
# a system directory as a subdirectory # 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)) 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): def accessible_exe(exe):
# compilers may contain executable names (on Cray or user edited) # compilers may contain executable names (on Cray or user edited)
if not os.path.isabs(exe): if not os.path.isabs(exe):
exe = spack.util.executable.which_string(exe) exe = llnl.util.executable.which_string(exe)
if not exe: if not exe:
return False return False
return os.path.isfile(exe) and os.access(exe, os.X_OK) 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"): if real_version == spack.version.Version("unknown"):
return self.version return self.version
self._real_version = real_version self._real_version = real_version
except spack.util.executable.ProcessError: except llnl.util.executable.ProcessError:
self._real_version = self.version self._real_version = self.version
return self._real_version return self._real_version
@@ -422,7 +422,7 @@ def _get_compiler_link_paths(self, paths):
csource.write( csource.write(
"int main(int argc, char* argv[]) { " "(void)argc; (void)argv; return 0; }\n" "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_type in flags:
for flag in self.flags.get(flag_type, []): for flag in self.flags.get(flag_type, []):
compiler_exe.add_default_arg(flag) 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) compiler_exe(self.verbose_flag, fin, "-o", fout, output=str, error=str)
) # str for py2 ) # str for py2
return _parse_non_system_link_dirs(output) 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) tty.debug("ProcessError: Command exited with non-zero status: " + pe.long_message)
return [] return []
finally: finally:
@@ -532,7 +532,7 @@ def get_real_version(self):
Use the runtime environment of the compiler (modules and environment Use the runtime environment of the compiler (modules and environment
modifications) to enable the compiler to run properly on any platform. 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(): with self.compiler_environment():
output = cc( output = cc(
self.version_argument, self.version_argument,
@@ -658,7 +658,7 @@ def compiler_environment(self):
spack.util.module_cmd.load_module(module) spack.util.module_cmd.load_module(module)
# apply other compiler environment changes # apply other compiler environment changes
env = spack.util.environment.EnvironmentModifications() env = llnl.util.envmod.EnvironmentModifications()
env.extend(spack.schema.environment.parse(self.environment)) env.extend(spack.schema.environment.parse(self.environment))
env.apply_modifications() env.apply_modifications()

View File

@@ -17,6 +17,7 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.lang import llnl.util.lang
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.envmod import get_path
import spack.compiler import spack.compiler
import spack.config import spack.config
@@ -24,7 +25,6 @@
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.spec import spack.spec
from spack.util.environment import get_path
from spack.util.naming import mod_to_class from spack.util.naming import mod_to_class
_path_instance_vars = ["cc", "cxx", "f77", "fc"] _path_instance_vars = ["cc", "cxx", "f77", "fc"]
@@ -680,7 +680,7 @@ def _default(fn_args):
return value, None return value, None
error = "Couldn't get version for compiler {0}".format(path) 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) error = "Couldn't get version for compiler {0}\n".format(path) + str(e)
except Exception as e: except Exception as e:
# Catching "Exception" here is fine because it just # Catching "Exception" here is fine because it just

View File

@@ -6,13 +6,13 @@
import re import re
import shutil import shutil
import llnl.util.executable
import llnl.util.lang import llnl.util.lang
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.symlink import symlink from llnl.util.symlink import symlink
import spack.compiler import spack.compiler
import spack.compilers.clang import spack.compilers.clang
import spack.util.executable
import spack.version import spack.version
@@ -90,13 +90,13 @@ def setup_custom_environment(self, pkg, env):
# Use special XCode versions of compiler wrappers when using XCode # Use special XCode versions of compiler wrappers when using XCode
# Overwrites build_environment's setting of SPACK_CC and SPACK_CXX # 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_clang = xcrun("-f", "clang", output=str).strip()
xcode_clangpp = 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_CC", xcode_clang, force=True)
env.set("SPACK_CXX", xcode_clangpp, 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 # Get the path of the active developer directory
real_root = xcode_select("--print-path", output=str).strip() real_root = xcode_select("--print-path", output=str).strip()

View File

@@ -6,11 +6,11 @@
import os import os
import re import re
import llnl.util.executable
from llnl.util.filesystem import ancestor from llnl.util.filesystem import ancestor
import spack.compiler import spack.compiler
import spack.compilers.apple_clang as apple_clang import spack.compilers.apple_clang as apple_clang
import spack.util.executable
from spack.version import ver from spack.version import ver
@@ -204,7 +204,7 @@ def stdcxx_libs(self):
def prefix(self): def prefix(self):
# GCC reports its install prefix when running ``-print-search-dirs`` # GCC reports its install prefix when running ``-print-search-dirs``
# on the first line ``install: <prefix>``. # on the first line ``install: <prefix>``.
cc = spack.util.executable.Executable(self.cc) cc = llnl.util.executable.Executable(self.cc)
with self.compiler_environment(): with self.compiler_environment():
gcc_output = cc("-print-search-dirs", output=str, error=str) gcc_output = cc("-print-search-dirs", output=str, error=str)

View File

@@ -10,10 +10,11 @@
from distutils.version import StrictVersion from distutils.version import StrictVersion
from typing import Dict, List, Set from typing import Dict, List, Set
import llnl.util.executable
import spack.compiler import spack.compiler
import spack.operating_systems.windows_os import spack.operating_systems.windows_os
import spack.platforms import spack.platforms
import spack.util.executable
from spack.compiler import Compiler from spack.compiler import Compiler
from spack.error import SpackError from spack.error import SpackError
from spack.version import Version from spack.version import Version
@@ -170,7 +171,7 @@ def fc_version(cls, fc):
sps = spack.operating_systems.windows_os.WindowsOs.compiler_search_paths sps = spack.operating_systems.windows_os.WindowsOs.compiler_search_paths
except AttributeError: except AttributeError:
raise SpackError("Windows compiler search paths not established") 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) ver = cls.default_version(clp)
else: else:
ver = fc_ver ver = fc_ver

View File

@@ -347,7 +347,7 @@ def find_win32_additional_install_paths():
windows_search_ext.extend( windows_search_ext.extend(
spack.config.get("config:additional_external_search_paths", default=[]) 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 return windows_search_ext

View File

@@ -12,10 +12,10 @@
import sys import sys
import warnings import warnings
import llnl.util.envmod
import llnl.util.filesystem import llnl.util.filesystem
import llnl.util.tty import llnl.util.tty
import spack.util.environment
import spack.util.ld_so_conf import spack.util.ld_so_conf
from .common import ( # find_windows_compiler_bundled_packages, 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 = (
path_hints path_hints
or spack.util.environment.get_path("LD_LIBRARY_PATH") or llnl.util.envmod.get_path("LD_LIBRARY_PATH")
+ spack.util.environment.get_path("DYLD_LIBRARY_PATH") + llnl.util.envmod.get_path("DYLD_LIBRARY_PATH")
+ spack.util.environment.get_path("DYLD_FALLBACK_LIBRARY_PATH") + llnl.util.envmod.get_path("DYLD_FALLBACK_LIBRARY_PATH")
+ spack.util.ld_so_conf.host_dynamic_linker_search_paths() + spack.util.ld_so_conf.host_dynamic_linker_search_paths()
) )
search_paths = llnl.util.filesystem.search_paths_for_libraries(*path_hints) 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): 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) search_paths = llnl.util.filesystem.search_paths_for_libraries(*path_hints)
# on Windows, some libraries (.dlls) are found in the bin directory or sometimes # 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 # 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 path_hints (list): list of paths to be searched. If None the list will be
constructed based on the PATH environment variable. 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) exe_pattern_to_pkgs = collections.defaultdict(list)
for pkg in packages_to_check: for pkg in packages_to_check:
if hasattr(pkg, "executables"): if hasattr(pkg, "executables"):

View File

@@ -20,6 +20,7 @@
import spack.spec import spack.spec
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
from spack.error import SpackError from spack.error import SpackError
from spack.util.environment import get_host_environment_metadata
is_windows = sys.platform == "win32" is_windows = sys.platform == "win32"
# Note: Posixpath is used here as opposed to # 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 versioning. We use it in the case that an analysis later needs to
easily access this information. easily access this information.
""" """
from spack.util.environment import get_host_environment_metadata
env_file = self.env_metadata_path(spec) env_file = self.env_metadata_path(spec)
environ = get_host_environment_metadata() environ = get_host_environment_metadata()
with open(env_file, "w") as fd: with open(env_file, "w") as fd:

View File

@@ -16,6 +16,7 @@
import ruamel.yaml as yaml import ruamel.yaml as yaml
import llnl.util.envmod
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.lang import dedupe from llnl.util.lang import dedupe
@@ -1535,7 +1536,7 @@ def check_views(self):
) )
def _env_modifications_for_default_view(self, reverse=False): def _env_modifications_for_default_view(self, reverse=False):
all_mods = spack.util.environment.EnvironmentModifications() all_mods = llnl.util.envmod.EnvironmentModifications()
visited = set() visited = set()
@@ -1576,7 +1577,7 @@ def add_default_view_to_env(self, env_mod):
default view. Removes duplicate paths. default view. Removes duplicate paths.
Args: Args:
env_mod (spack.util.environment.EnvironmentModifications): the environment env_mod (llnl.util.envmod.EnvironmentModifications): the environment
modifications object that is modified. modifications object that is modified.
""" """
if default_view_name not in self.views: 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``. default view. Reverses the action of ``add_default_view_to_env``.
Args: Args:
env_mod (spack.util.environment.EnvironmentModifications): the environment env_mod (llnl.util.envmod.EnvironmentModifications): the environment
modifications object that is modified. modifications object that is modified.
""" """
if default_view_name not in self.views: if default_view_name not in self.views:

View File

@@ -5,12 +5,12 @@
import os import os
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.envmod import EnvironmentModifications
from llnl.util.tty.color import colorize from llnl.util.tty.color import colorize
import spack.environment as ev import spack.environment as ev
import spack.repo import spack.repo
import spack.store import spack.store
from spack.util.environment import EnvironmentModifications
def activate_header(env, shell, prompt=None): 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 add_view (bool): generate commands to add view to path variables
Returns: Returns:
spack.util.environment.EnvironmentModifications: Environment variables llnl.util.envmod.EnvironmentModifications: Environment variables
modifications to activate environment. modifications to activate environment.
""" """
ev.activate(env, use_env_repo=use_env_repo) ev.activate(env, use_env_repo=use_env_repo)
@@ -150,7 +150,7 @@ def deactivate():
after activation are not unloaded. after activation are not unloaded.
Returns: Returns:
spack.util.environment.EnvironmentModifications: Environment variables llnl.util.envmod.EnvironmentModifications: Environment variables
modifications to activate environment. modifications to activate environment.
""" """
env_mods = EnvironmentModifications() env_mods = EnvironmentModifications()

View File

@@ -35,6 +35,7 @@
import llnl.util import llnl.util
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import CommandNotFoundError, which
from llnl.util.filesystem import ( from llnl.util.filesystem import (
get_single_file, get_single_file,
mkdirp, mkdirp,
@@ -42,6 +43,7 @@
temp_rename, temp_rename,
working_dir, working_dir,
) )
from llnl.util.string import comma_and, quote
from llnl.util.symlink import symlink from llnl.util.symlink import symlink
import spack.config import spack.config
@@ -54,8 +56,6 @@
import spack.util.web as web_util import spack.util.web as web_util
import spack.version import spack.version
from spack.util.compression import decompressor_for, extension_from_path 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. #: List of all fetch strategies, created by FetchStrategy metaclass.
all_strategies = [] all_strategies = []

View File

@@ -6,6 +6,7 @@
import os import os
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import Executable
from llnl.util.filesystem import BaseDirectoryVisitor, visit_directory_tree from llnl.util.filesystem import BaseDirectoryVisitor, visit_directory_tree
from llnl.util.lang import elide_list from llnl.util.lang import elide_list
@@ -13,7 +14,6 @@
import spack.config import spack.config
import spack.relocate import spack.relocate
from spack.util.elf import ElfParsingError, parse_elf from spack.util.elf import ElfParsingError, parse_elf
from spack.util.executable import Executable
def is_shared_library_elf(filepath): def is_shared_library_elf(filepath):

View File

@@ -6,11 +6,11 @@
import os import os
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import Executable, which
from llnl.util.filesystem import mkdirp from llnl.util.filesystem import mkdirp
from llnl.util.symlink import symlink from llnl.util.symlink import symlink
from spack.util.editor import editor from spack.util.editor import editor
from spack.util.executable import Executable, which
def pre_install(spec): def pre_install(spec):

View File

@@ -13,6 +13,7 @@
import spack.error import spack.error
import spack.paths import spack.paths
import spack.util.path
import spack.util.prefix import spack.util.prefix
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
from spack.spec import Spec from spack.spec import Spec

View File

@@ -40,6 +40,8 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.lock as lk import llnl.util.lock as lk
import llnl.util.tty as tty 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.lang import pretty_seconds
from llnl.util.tty.color import colorize from llnl.util.tty.color import colorize
from llnl.util.tty.log import log_output from llnl.util.tty.log import log_output
@@ -53,11 +55,9 @@
import spack.package_prefs as prefs import spack.package_prefs as prefs
import spack.repo import spack.repo
import spack.store import spack.store
import spack.util.executable
import spack.util.path import spack.util.path
import spack.util.timer as timer import spack.util.timer as timer
from spack.util.environment import EnvironmentModifications, dump_environment from spack.util.environment import dump_environment
from spack.util.executable import which
#: Counter to support unique spec sequencing that is used to ensure packages #: 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 #: with the same priority are (initially) processed in the order in which they

View File

@@ -26,6 +26,7 @@
import archspec.cpu import archspec.cpu
import llnl.util.envmod
import llnl.util.lang import llnl.util.lang
import llnl.util.tty as tty import llnl.util.tty as tty
import llnl.util.tty.colify import llnl.util.tty.colify
@@ -44,9 +45,7 @@
import spack.spec import spack.spec
import spack.store import spack.store
import spack.util.debug import spack.util.debug
import spack.util.environment
import spack.util.git import spack.util.git
import spack.util.path
from spack.error import SpackError from spack.error import SpackError
#: names of profile statistics #: names of profile statistics
@@ -575,7 +574,7 @@ def setup_main_options(args):
if args.debug: if args.debug:
spack.util.debug.register_interrupt_handler() spack.util.debug.register_interrupt_handler()
spack.config.set("config:debug", True, scope="command_line") spack.config.set("config:debug", True, scope="command_line")
spack.util.environment.tracing_enabled = True llnl.util.envmod.tracing_enabled = True
if args.timestamp: if args.timestamp:
tty.set_timestamp(True) tty.set_timestamp(True)

View File

@@ -36,6 +36,7 @@
import re import re
from typing import Optional from typing import Optional
import llnl.util.envmod
import llnl.util.filesystem import llnl.util.filesystem
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.lang import dedupe from llnl.util.lang import dedupe
@@ -51,7 +52,6 @@
import spack.schema.environment import spack.schema.environment
import spack.store import spack.store
import spack.tengine as tengine import spack.tengine as tengine
import spack.util.environment
import spack.util.file_permissions as fp import spack.util.file_permissions as fp
import spack.util.path import spack.util.path
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
@@ -732,8 +732,8 @@ def environment_modifications(self):
spec.prefix = view.get_projection_for_spec(spec) spec.prefix = view.get_projection_for_spec(spec)
env = spack.util.environment.inspect_path( env = llnl.util.envmod.inspect_path(
spec.prefix, prefix_inspections, exclude=spack.util.environment.is_system_path spec.prefix, prefix_inspections, exclude=llnl.util.envmod.is_system_path
) )
# Let the extendee/dependency modify their extensions/dependencies # Let the extendee/dependency modify their extensions/dependencies

View File

@@ -9,6 +9,7 @@
import posixpath import posixpath
from typing import Any, Dict from typing import Any, Dict
import llnl.util.envmod
import llnl.util.lang as lang import llnl.util.lang as lang
import spack.compilers import spack.compilers
@@ -17,7 +18,6 @@
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.tengine as tengine import spack.tengine as tengine
import spack.util.environment
from .common import BaseConfiguration, BaseContext, BaseFileLayout, BaseModuleFileWriter 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 # A compiler is considered to be a core compiler if any of the
# C, C++ or Fortran compilers reside in a system directory # C, C++ or Fortran compilers reside in a system directory
is_system_compiler = any( 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() for x in compiler["paths"].values()
if x is not None if x is not None
) )

View File

@@ -10,8 +10,8 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.lang import llnl.util.lang
import llnl.util.tty as tty 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 spack.util.module_cmd import module
from .linux_distro import LinuxDistro from .linux_distro import LinuxDistro

View File

@@ -8,8 +8,8 @@
import re import re
import llnl.util.lang import llnl.util.lang
from llnl.util.executable import Executable
from spack.util.executable import Executable
from spack.version import Version from spack.version import Version
from ._operating_system import OperatingSystem from ._operating_system import OperatingSystem
@@ -50,7 +50,7 @@ def macos_version():
try: try:
output = Executable("sw_vers")(output=str, fail_on_error=False) output = Executable("sw_vers")(output=str, fail_on_error=False)
except Exception: except Exception:
# FileNotFoundError, or spack.util.executable.ProcessError # FileNotFoundError, or llnl.util.executable.ProcessError
pass pass
else: else:
match = re.search(r"ProductVersion:\s*([0-9.]+)", output) match = re.search(r"ProductVersion:\s*([0-9.]+)", output)

View File

@@ -19,12 +19,12 @@
# import most common types used in packages # import most common types used in packages
from typing import Dict, List, Optional from typing import Dict, List, Optional
import llnl.util.executable
import llnl.util.filesystem import llnl.util.filesystem
from llnl.util.executable import *
from llnl.util.filesystem import * from llnl.util.filesystem import *
from llnl.util.symlink import symlink from llnl.util.symlink import symlink
import spack.util.executable
# These props will be overridden when the build env is set up. # These props will be overridden when the build env is set up.
from spack.build_environment import MakeExecutable from spack.build_environment import MakeExecutable
from spack.build_systems.aspell_dict import AspellDictPackage from spack.build_systems.aspell_dict import AspellDictPackage
@@ -87,7 +87,6 @@
on_package_attributes, on_package_attributes,
) )
from spack.spec import InvalidSpecDetected, Spec from spack.spec import InvalidSpecDetected, Spec
from spack.util.executable import *
from spack.variant import ( from spack.variant import (
any_combination_of, any_combination_of,
auto_or_any_combination_of, auto_or_any_combination_of,

View File

@@ -29,8 +29,11 @@
import warnings import warnings
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type
import llnl.util.envmod
import llnl.util.filesystem as fsys import llnl.util.filesystem as fsys
import llnl.util.path
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import ProcessError, which
from llnl.util.lang import classproperty, memoized, nullcontext from llnl.util.lang import classproperty, memoized, nullcontext
from llnl.util.link_tree import LinkTree from llnl.util.link_tree import LinkTree
@@ -51,14 +54,12 @@
import spack.spec import spack.spec
import spack.store import spack.store
import spack.url import spack.url
import spack.util.environment
import spack.util.path import spack.util.path
import spack.util.web import spack.util.web
from spack.filesystem_view import YamlFilesystemView from spack.filesystem_view import YamlFilesystemView
from spack.install_test import TestFailure, TestSuite from spack.install_test import TestFailure, TestSuite
from spack.installer import InstallError, PackageInstaller from spack.installer import InstallError, PackageInstaller
from spack.stage import ResourceStage, Stage, StageComposite, stage_prefix 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.package_hash import package_hash
from spack.util.prefix import Prefix from spack.util.prefix import Prefix
from spack.util.web import FetchError from spack.util.web import FetchError
@@ -204,9 +205,9 @@ def __init__(cls, name, bases, attr_dict):
def platform_executables(cls): def platform_executables(cls):
def to_windows_exe(exe): def to_windows_exe(exe):
if exe.endswith("$"): if exe.endswith("$"):
exe = exe.replace("$", "%s$" % spack.util.path.win_exe_ext()) exe = exe.replace("$", "%s$" % llnl.util.path.win_exe_ext())
else: else:
exe += spack.util.path.win_exe_ext() exe += llnl.util.path.win_exe_ext()
return exe return exe
plat_exe = [] plat_exe = []
@@ -1993,7 +1994,7 @@ def run_test(
for line in out: for line in out:
print(line.rstrip("\n")) print(line.rstrip("\n"))
if exc_type is spack.util.executable.ProcessError: if exc_type is llnl.util.executable.ProcessError:
out = io.StringIO() out = io.StringIO()
spack.build_environment.write_log_summary( spack.build_environment.write_log_summary(
out, "test", self.test_log_file, last=1 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. """Sets up the run environment for a package.
Args: Args:
env (spack.util.environment.EnvironmentModifications): environment env (llnl.util.envmod.EnvironmentModifications): environment
modifications to be applied when the package is run. Package authors modifications to be applied when the package is run. Package authors
can call methods on it to alter the run environment. 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. for dependencies.
Args: Args:
env (spack.util.environment.EnvironmentModifications): environment env (llnl.util.envmod.EnvironmentModifications): environment
modifications to be applied when the dependent package is run. modifications to be applied when the dependent package is run.
Package authors can call methods on it to alter the build environment. Package authors can call methods on it to alter the build environment.

View File

@@ -5,7 +5,7 @@
import os 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): def compile_c_and_execute(source_file, include_flags, link_flags):

View File

@@ -11,6 +11,7 @@
import llnl.util.filesystem import llnl.util.filesystem
import llnl.util.lang import llnl.util.lang
from llnl.util.executable import which, which_string
import spack import spack
import spack.error import spack.error
@@ -20,19 +21,9 @@
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
from spack.util.compression import allowed_archive from spack.util.compression import allowed_archive
from spack.util.crypto import Checker, checksum 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="."): def get_patch_exe():
"""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 '.')
"""
git_utils_path = os.environ.get("PATH", "") git_utils_path = os.environ.get("PATH", "")
if sys.platform == "win32": if sys.platform == "win32":
git = which_string("git", required=True) 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 # Note for future developers: The GNU port of patch to windows
# has issues handling CRLF line endings unless the --binary # has issues handling CRLF line endings unless the --binary
# flag is passed. # 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): with llnl.util.filesystem.working_dir(stage.source_path):
patch("-s", "-p", str(level), "-i", patch_path, "-d", working_dir) patch("-s", "-p", str(level), "-i", patch_path, "-d", working_dir)

View File

@@ -4,10 +4,9 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import contextlib import contextlib
import llnl.util.envmod
import llnl.util.lang import llnl.util.lang
import spack.util.environment
from .cray import Cray from .cray import Cray
from .darwin import Darwin from .darwin import Darwin
from .linux import Linux from .linux import Linux
@@ -64,7 +63,7 @@ def prevent_cray_detection():
"""Context manager that prevents the detection of the Cray platform""" """Context manager that prevents the detection of the Cray platform"""
reset() reset()
try: try:
with spack.util.environment.set_env(MODULEPATH=""): with llnl.util.envmod.set_env(MODULEPATH=""):
yield yield
finally: finally:
reset() reset()

View File

@@ -10,13 +10,13 @@
import archspec.cpu import archspec.cpu
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.executable import Executable
import spack.target import spack.target
import spack.version import spack.version
from spack.operating_systems.cray_backend import CrayBackend from spack.operating_systems.cray_backend import CrayBackend
from spack.operating_systems.cray_frontend import CrayFrontend from spack.operating_systems.cray_frontend import CrayFrontend
from spack.paths import build_env_path from spack.paths import build_env_path
from spack.util.executable import Executable
from spack.util.module_cmd import module from spack.util.module_cmd import module
from ._platform import NoPlatformError, Platform from ._platform import NoPlatformError, Platform

View File

@@ -12,6 +12,7 @@
import macholib.mach_o import macholib.mach_o
import macholib.MachO import macholib.MachO
import llnl.util.executable as executable
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.lang import llnl.util.lang
import llnl.util.tty as tty import llnl.util.tty as tty
@@ -24,7 +25,6 @@
import spack.spec import spack.spec
import spack.store import spack.store
import spack.util.elf as elf import spack.util.elf as elf
import spack.util.executable as executable
is_macos = str(spack.platforms.real_host()) == "darwin" is_macos = str(spack.platforms.real_host()) == "darwin"

View File

@@ -30,6 +30,7 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.lang import llnl.util.lang
import llnl.util.path
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import working_dir from llnl.util.filesystem import working_dir
@@ -563,7 +564,7 @@ def __init__(self, package_checker, namespace, cache):
self.checker = package_checker self.checker = package_checker
self.packages_path = self.checker.packages_path self.packages_path = self.checker.packages_path
if sys.platform == "win32": 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.namespace = namespace
self.indexers = {} self.indexers = {}

View File

@@ -40,9 +40,9 @@ def parse(config_obj):
config_obj: a configuration dictionary conforming to the config_obj: a configuration dictionary conforming to the
schema definition for environment modifications 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(): for command, variable in config_obj.items():
# Distinguish between commands that take only a name as argument # Distinguish between commands that take only a name as argument
# (e.g. unset) and commands that take a name and a value. # (e.g. unset) and commands that take a name and a value.

View File

@@ -59,8 +59,11 @@
import ruamel.yaml as yaml import ruamel.yaml as yaml
import llnl.util.executable
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.lang as lang 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 as tty
import llnl.util.tty.color as clr import llnl.util.tty.color as clr
@@ -79,14 +82,11 @@
import spack.target import spack.target
import spack.traverse as traverse import spack.traverse as traverse
import spack.util.crypto import spack.util.crypto
import spack.util.executable
import spack.util.hash import spack.util.hash
import spack.util.module_cmd as md import spack.util.module_cmd as md
import spack.util.path as pth
import spack.util.prefix import spack.util.prefix
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
import spack.util.string
import spack.variant as vt import spack.variant as vt
import spack.version as vn import spack.version as vn
@@ -988,7 +988,7 @@ def _command_default_handler(descriptor, spec, cls):
path = os.path.join(home.bin, spec.name) path = os.path.join(home.bin, spec.name)
if fs.is_exe(path): if fs.is_exe(path):
return spack.util.executable.Executable(path) return llnl.util.executable.Executable(path)
else: else:
msg = "Unable to locate {0} command in {1}" msg = "Unable to locate {0} command in {1}"
raise RuntimeError(msg.format(spec.name, home.bin)) raise RuntimeError(msg.format(spec.name, home.bin))
@@ -5041,7 +5041,7 @@ class InvalidDependencyError(spack.error.SpecError):
def __init__(self, pkg, deps): def __init__(self, pkg, deps):
self.invalid_deps = deps self.invalid_deps = deps
super(InvalidDependencyError, self).__init__( 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))
) )

View File

@@ -28,6 +28,7 @@
partition_path, partition_path,
remove_linked_tree, remove_linked_tree,
) )
from llnl.util.path import sanitize_file_path
import spack.caches import spack.caches
import spack.config import spack.config
@@ -378,7 +379,7 @@ def expected_archive_files(self):
expanded = True expanded = True
if isinstance(self.default_fetcher, fs.URLFetchStrategy): if isinstance(self.default_fetcher, fs.URLFetchStrategy):
expanded = self.default_fetcher.expand_archive 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) fnames.append(clean_url)
if self.mirror_paths: if self.mirror_paths:

View File

@@ -7,6 +7,7 @@
import archspec.cpu import archspec.cpu
import llnl.util.executable
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.compiler import spack.compiler
@@ -161,7 +162,7 @@ def optimization_flags(self, compiler):
compiler = spack.compilers.compilers_for_spec(compiler).pop() compiler = spack.compilers.compilers_for_spec(compiler).pop()
try: try:
compiler_version = compiler.real_version 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 # log this and just return compiler.version instead
tty.debug(str(e)) tty.debug(str(e))

View File

@@ -10,7 +10,10 @@
import pytest import pytest
from llnl.util.envmod import EnvironmentModifications
from llnl.util.executable import Executable
from llnl.util.filesystem import HeaderList, LibraryList from llnl.util.filesystem import HeaderList, LibraryList
from llnl.util.path import Path, convert_to_platform_path
import spack.build_environment import spack.build_environment
import spack.config import spack.config
@@ -23,9 +26,6 @@
dso_suffix, dso_suffix,
) )
from spack.paths import build_env_path 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): def os_pathsep_join(path, *pths):

View File

@@ -7,9 +7,10 @@
import pytest import pytest
import llnl.util.executable
import spack.cmd.create import spack.cmd.create
import spack.stage import spack.stage
import spack.util.executable
import spack.util.url as url_util import spack.util.url as url_util
pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows") 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 appropriate file name and returns their url along with
the correct build-system guess the correct build-system guess
""" """
tar = spack.util.executable.which("tar") tar = llnl.util.executable.which("tar")
orig_dir = tmpdir.chdir() orig_dir = tmpdir.chdir()
filename, system = request.param filename, system = request.param
tmpdir.ensure("archive", filename) tmpdir.ensure("archive", filename)

View File

@@ -11,6 +11,7 @@
import pytest import pytest
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
from llnl.util.executable import which
import spack.build_systems.autotools import spack.build_systems.autotools
import spack.build_systems.cmake import spack.build_systems.cmake
@@ -19,7 +20,6 @@
import spack.repo import spack.repo
from spack.build_environment import ChildError, setup_package from spack.build_environment import ChildError, setup_package
from spack.spec import Spec from spack.spec import Spec
from spack.util.executable import which
DATA_PATH = os.path.join(spack.paths.test_path, "data") DATA_PATH = os.path.join(spack.paths.test_path, "data")

View File

@@ -12,12 +12,13 @@
import pytest import pytest
from llnl.util.envmod import set_env, system_dirs
from llnl.util.executable import Executable, ProcessError
import spack.build_environment import spack.build_environment
import spack.config import spack.config
import spack.spec import spack.spec
from spack.paths import build_env_path 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 # Complicated compiler test command

View File

@@ -7,13 +7,14 @@
import pytest import pytest
from llnl.util.path import convert_to_posix_path
import spack.bootstrap import spack.bootstrap
import spack.bootstrap.core import spack.bootstrap.core
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
import spack.main import spack.main
import spack.mirror import spack.mirror
from spack.util.path import convert_to_posix_path
_bootstrap = spack.main.SpackCommand("bootstrap") _bootstrap = spack.main.SpackCommand("bootstrap")

View File

@@ -7,11 +7,12 @@
import pytest import pytest
from llnl.util.executable import which
import spack.cmd.create import spack.cmd.create
import spack.util.editor import spack.util.editor
from spack.main import SpackCommand from spack.main import SpackCommand
from spack.url import UndetectableNameError from spack.url import UndetectableNameError
from spack.util.executable import which
create = SpackCommand("create") create = SpackCommand("create")

View File

@@ -10,10 +10,11 @@
import pytest import pytest
from llnl.util.executable import which
import spack.config import spack.config
import spack.platforms import spack.platforms
from spack.main import SpackCommand, get_version from spack.main import SpackCommand, get_version
from spack.util.executable import which
debug = SpackCommand("debug") debug = SpackCommand("debug")

View File

@@ -12,6 +12,7 @@
import spack.environment as ev import spack.environment as ev
import spack.spec import spack.spec
import spack.util.path
from spack.main import SpackCommand from spack.main import SpackCommand
develop = SpackCommand("develop") develop = SpackCommand("develop")

View File

@@ -14,6 +14,7 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.link_tree import llnl.util.link_tree
from llnl.util.executable import Executable
import spack.cmd.env import spack.cmd.env
import spack.config import spack.config
@@ -28,7 +29,6 @@
from spack.main import SpackCommand, SpackCommandError from spack.main import SpackCommand, SpackCommandError
from spack.spec import Spec from spack.spec import Spec
from spack.stage import stage_prefix from spack.stage import stage_prefix
from spack.util.executable import Executable
from spack.util.path import substitute_path_variables from spack.util.path import substitute_path_variables
from spack.version import Version 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.install_all()
e.write() e.write()
env_mod = spack.util.environment.EnvironmentModifications() env_mod = llnl.util.envmod.EnvironmentModifications()
e.add_default_view_to_env(env_mod) e.add_default_view_to_env(env_mod)
env_variables = {} env_variables = {}
env_mod.apply_modifications(env_variables) env_mod.apply_modifications(env_variables)

View File

@@ -8,6 +8,7 @@
import pytest import pytest
import llnl.util.path
from llnl.util.filesystem import getuid, touch from llnl.util.filesystem import getuid, touch
import spack import spack
@@ -35,7 +36,7 @@ def _platform_executables(monkeypatch):
def _win_exe_ext(): def _win_exe_ext():
return ".bat" 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): def define_plat_exe(exe):

View File

@@ -9,13 +9,12 @@
import pytest import pytest
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
from llnl.util.executable import ProcessError
import spack.bootstrap import spack.bootstrap
import spack.util.executable
import spack.util.gpg import spack.util.gpg
from spack.main import SpackCommand from spack.main import SpackCommand
from spack.paths import mock_gpg_data_path, mock_gpg_keys_path from spack.paths import mock_gpg_data_path, mock_gpg_keys_path
from spack.util.executable import ProcessError
#: spack command used by tests below #: spack command used by tests below
gpg = SpackCommand("gpg") gpg = SpackCommand("gpg")

View File

@@ -23,7 +23,6 @@
import spack.environment as ev import spack.environment as ev
import spack.hash_types as ht import spack.hash_types as ht
import spack.package_base import spack.package_base
import spack.util.executable
from spack.error import SpackError from spack.error import SpackError
from spack.main import SpackCommand from spack.main import SpackCommand
from spack.parser import SpecSyntaxError from spack.parser import SpecSyntaxError

View File

@@ -9,13 +9,13 @@
import pytest import pytest
from llnl.util.executable import which
from llnl.util.filesystem import FileFilter from llnl.util.filesystem import FileFilter
import spack.main import spack.main
import spack.paths import spack.paths
import spack.repo import spack.repo
from spack.cmd.style import changed_files from spack.cmd.style import changed_files
from spack.util.executable import which
#: directory with sample style files #: directory with sample style files
style_data = os.path.join(spack.paths.test_path, "data", "style") style_data = os.path.join(spack.paths.test_path, "data", "style")

View File

@@ -5,6 +5,7 @@
import argparse import argparse
import os import os
import re
import sys import sys
import pytest import pytest
@@ -105,7 +106,7 @@ def test_test_output_on_error(
out = spack_test("run", "test-error", fail_on_error=False) out = spack_test("run", "test-error", fail_on_error=False)
assert "TestFailure" in out 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( def test_test_output_on_failure(
@@ -137,7 +138,7 @@ def test_show_log_on_error(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"pkg_name,msgs", "pkg_name,msgs",
[ [
("test-error", ["FAILED: Command exited", "TestFailure"]), ("test-error", ["FAILED: Command &#39;", "TestFailure"]),
("test-fail", ["FAILED: Expected", "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") report_file = report_dir.join("test-error_Testing.xml")
assert report_file in report_dir.listdir() assert report_file in report_dir.listdir()
content = report_file.open().read() 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( def test_cdash_upload_clean_test(

View File

@@ -10,14 +10,14 @@
import pytest import pytest
import llnl.util.envmod
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
from llnl.util.executable import ProcessError
import spack.compiler import spack.compiler
import spack.compilers as compilers import spack.compilers as compilers
import spack.spec import spack.spec
import spack.util.environment
from spack.compiler import Compiler from spack.compiler import Compiler
from spack.util.executable import ProcessError
@pytest.fixture() @pytest.fixture()
@@ -215,7 +215,7 @@ def call_compiler(exe, *args, **kwargs):
def test_get_compiler_link_paths(monkeypatch, exe, flagname): def test_get_compiler_link_paths(monkeypatch, exe, flagname):
# create fake compiler that emits mock verbose output # create fake compiler that emits mock verbose output
compiler = MockCompiler() 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 # Grab executable path to test
paths = [getattr(compiler, exe)] paths = [getattr(compiler, exe)]
@@ -798,7 +798,7 @@ def module(*args):
def _call(*args, **kwargs): def _call(*args, **kwargs):
raise ProcessError("Failed intentionally") 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 # Run and no change to environment
compilers = spack.compilers.get_compilers([compiler_dict]) compilers = spack.compilers.get_compilers([compiler_dict])
@@ -868,7 +868,7 @@ class MockPackage(object):
"x86_64", "x86_64",
["/usr/bin/clang", "/usr/bin/clang++", None, None], ["/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 # Check a package that doesn't use xcode and ensure we don't add changes
# to the environment # to the environment
pkg = MockPackage() pkg = MockPackage()
@@ -955,7 +955,7 @@ def test_xcode_not_available(xcode_select_output, mock_executable, monkeypatch):
"x86_64", "x86_64",
["/usr/bin/clang", "/usr/bin/clang++", None, None], ["/usr/bin/clang", "/usr/bin/clang++", None, None],
) )
env = spack.util.environment.EnvironmentModifications() env = llnl.util.envmod.EnvironmentModifications()
class MockPackage(object): class MockPackage(object):
use_xcode = True use_xcode = True

View File

@@ -24,6 +24,7 @@
import archspec.cpu.microarchitecture import archspec.cpu.microarchitecture
import archspec.cpu.schema import archspec.cpu.schema
import llnl.util.executable
import llnl.util.lang import llnl.util.lang
import llnl.util.lock import llnl.util.lock
import llnl.util.tty as tty import llnl.util.tty as tty
@@ -45,7 +46,6 @@
import spack.store import spack.store
import spack.subprocess_context import spack.subprocess_context
import spack.test.cray_manifest import spack.test.cray_manifest
import spack.util.executable
import spack.util.git import spack.util.git
import spack.util.gpg import spack.util.gpg
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
@@ -511,7 +511,7 @@ def _skip_if_missing_executables(request):
if marker: if marker:
required_execs = marker.args 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: if missing_execs:
msg = "could not find executables: {0}" msg = "could not find executables: {0}"
pytest.skip(msg.format(", ".join(missing_execs))) 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 """Creates a very simple archive directory with a configure script and a
makefile that installs to a prefix. Tars it up into an archive. 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: if not tar:
pytest.skip("requires tar to be installed") pytest.skip("requires tar to be installed")
@@ -1168,7 +1168,7 @@ def _parse_cvs_date(line):
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def mock_cvs_repository(tmpdir_factory): def mock_cvs_repository(tmpdir_factory):
"""Creates a very simple CVS repository with two commits and a branch.""" """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 = tmpdir_factory.mktemp("mock-cvs-repo-dir")
tmpdir.ensure(spack.stage._source_path_subdir, dir=True) tmpdir.ensure(spack.stage._source_path_subdir, dir=True)
@@ -1460,7 +1460,7 @@ def mock_git_repository(git, tmpdir_factory):
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def mock_hg_repository(tmpdir_factory): def mock_hg_repository(tmpdir_factory):
"""Creates a very simple hg repository with two commits.""" """Creates a very simple hg repository with two commits."""
hg = spack.util.executable.which("hg") hg = llnl.util.executable.which("hg")
if not hg: if not hg:
pytest.skip("requires mercurial to be installed") pytest.skip("requires mercurial to be installed")
@@ -1500,11 +1500,11 @@ def mock_hg_repository(tmpdir_factory):
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def mock_svn_repository(tmpdir_factory): def mock_svn_repository(tmpdir_factory):
"""Creates a very simple svn repository with two commits.""" """Creates a very simple svn repository with two commits."""
svn = spack.util.executable.which("svn") svn = llnl.util.executable.which("svn")
if not svn: if not svn:
pytest.skip("requires svn to be installed") 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 = tmpdir_factory.mktemp("mock-svn-stage")
tmpdir.ensure(spack.stage._source_path_subdir, dir=True) tmpdir.ensure(spack.stage._source_path_subdir, dir=True)
@@ -1897,7 +1897,7 @@ def _factory(rpaths, message="Hello world!"):
message message
) )
) )
gcc = spack.util.executable.which("gcc") gcc = llnl.util.executable.which("gcc")
executable = source.dirpath("main.x") executable = source.dirpath("main.x")
# Encode relative RPATHs using `$ORIGIN` as the root prefix # 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] rpaths = [x if os.path.isabs(x) else os.path.join("$ORIGIN", x) for x in rpaths]

View File

@@ -7,12 +7,12 @@
import pytest import pytest
from llnl.util.executable import which
from llnl.util.filesystem import mkdirp, touch, working_dir from llnl.util.filesystem import mkdirp, touch, working_dir
from spack.fetch_strategy import CvsFetchStrategy from spack.fetch_strategy import CvsFetchStrategy
from spack.spec import Spec from spack.spec import Spec
from spack.stage import Stage from spack.stage import Stage
from spack.util.executable import which
from spack.version import ver from spack.version import ver
pytestmark = pytest.mark.skipif(not which("cvs"), reason="requires CVS to be installed") pytestmark = pytest.mark.skipif(not which("cvs"), reason="requires CVS to be installed")

View File

@@ -10,7 +10,7 @@ import sys
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.build_environment import spack.build_environment
import spack.util.executable import llnl.util.executable
from spack.package import * from spack.package import *
@@ -378,7 +378,7 @@ class Llvm(CMakePackage, CudaPackage):
match = version_regex.search(output) match = version_regex.search(output)
if match: if match:
return match.group(match.lastindex) return match.group(match.lastindex)
except spack.util.executable.ProcessError: except llnl.util.executable.ProcessError:
pass pass
except Exception as e: except Exception as e:
tty.debug(e) tty.debug(e)

View File

@@ -23,6 +23,7 @@
from jsonschema import validate from jsonschema import validate
import llnl.util.lock as lk import llnl.util.lock as lk
from llnl.util.executable import Executable
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
import spack.database import spack.database
@@ -31,7 +32,6 @@
import spack.spec import spack.spec
import spack.store import spack.store
from spack.schema.database_index import schema from spack.schema.database_index import schema
from spack.util.executable import Executable
is_windows = sys.platform == "win32" is_windows = sys.platform == "win32"

View File

@@ -11,6 +11,8 @@
import pytest import pytest
from llnl.util.path import path_to_os_path
import spack.paths import spack.paths
import spack.repo import spack.repo
from spack.directory_layout import ( from spack.directory_layout import (
@@ -18,7 +20,6 @@
InvalidDirectoryLayoutParametersError, InvalidDirectoryLayoutParametersError,
) )
from spack.spec import Spec from spack.spec import Spec
from spack.util.path import path_to_os_path
# number of packages to test (to reduce test time) # number of packages to test (to reduce test time)
max_packages = 10 max_packages = 10

View File

@@ -8,18 +8,9 @@
import pytest import pytest
import spack.util.environment as environment import llnl.util.envmod as envmod
from spack.paths import spack_root 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") 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("lib")
tmpdir.mkdir("include") tmpdir.mkdir("include")
env = environment.inspect_path(str(tmpdir), inspections) env = envmod.inspect_path(str(tmpdir), inspections)
names = [item.name for item in env] names = [item.name for item in env]
assert "PATH" in names assert "PATH" in names
assert "LIBRARY_PATH" in names assert "LIBRARY_PATH" in names
@@ -58,7 +49,7 @@ def test_exclude_paths_from_inspection():
"include": ["CPATH"], "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 assert len(env) == 0
@@ -79,7 +70,7 @@ def prepare_environment_for_tests(working_env):
@pytest.fixture @pytest.fixture
def env(prepare_environment_for_tests): def env(prepare_environment_for_tests):
"""Returns an empty EnvironmentModifications object.""" """Returns an empty EnvironmentModifications object."""
return EnvironmentModifications() return envmod.EnvironmentModifications()
@pytest.fixture @pytest.fixture
@@ -162,7 +153,7 @@ def test_unset(env):
@pytest.mark.skipif(sys.platform == "win32", reason="Not supported on Windows (yet)") @pytest.mark.skipif(sys.platform == "win32", reason="Not supported on Windows (yet)")
def test_filter_system_paths(miscellaneous_paths): def test_filter_system_paths(miscellaneous_paths):
"""Tests that the filtering of system paths works as expected.""" """Tests that the filtering of system paths works as expected."""
filtered = filter_system_paths(miscellaneous_paths) filtered = envmod.filter_system_paths(miscellaneous_paths)
expected = [ expected = [
"/usr/local/Cellar/gcc/5.3.0/lib", "/usr/local/Cellar/gcc/5.3.0/lib",
"/usr/local/opt/some-package/lib", "/usr/local/opt/some-package/lib",
@@ -246,7 +237,7 @@ def test_extend(env):
""" """
env.set("A", "dummy value") env.set("A", "dummy value")
env.set("B", 3) env.set("B", 3)
copy_construct = EnvironmentModifications(env) copy_construct = envmod.EnvironmentModifications(env)
assert len(copy_construct) == 2 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 """Tests the construction of a list of environment modifications that are
the result of sourcing a file. the result of sourcing a file.
""" """
env = EnvironmentModifications() env = envmod.EnvironmentModifications()
for filename in files_to_be_sourced: for filename in files_to_be_sourced:
if filename.endswith("sourceme_parameters.sh"): if filename.endswith("sourceme_parameters.sh"):
env.extend(EnvironmentModifications.from_sourcing_file(filename, "intel64")) env.extend(envmod.EnvironmentModifications.from_sourcing_file(filename, "intel64"))
else: else:
env.extend(EnvironmentModifications.from_sourcing_file(filename)) env.extend(envmod.EnvironmentModifications.from_sourcing_file(filename))
modifications = env.group_by_name() modifications = env.group_by_name()
@@ -277,28 +268,28 @@ def test_source_files(files_to_be_sourced):
# Set new variables # Set new variables
assert len(modifications["NEW_VAR"]) == 1 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 modifications["NEW_VAR"][0].value == "new"
assert len(modifications["FOO"]) == 1 assert len(modifications["FOO"]) == 1
assert isinstance(modifications["FOO"][0], SetEnv) assert isinstance(modifications["FOO"][0], envmod.SetEnv)
assert modifications["FOO"][0].value == "intel64" assert modifications["FOO"][0].value == "intel64"
# Unset variables # Unset variables
assert len(modifications["EMPTY_PATH_LIST"]) == 1 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 # Modified variables
assert len(modifications["UNSET_ME"]) == 1 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 modifications["UNSET_ME"][0].value == "overridden"
assert len(modifications["PATH_LIST"]) == 3 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 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 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" 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, # 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 # NOT_SET is not in the environment and will be set within the
# context manager, PATH_LIST is set and will be changed. # 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" os.environ["NOT_SET"] = "a"
assert 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") @pytest.mark.usefixtures("prepare_environment_for_tests")
def test_environment_from_sourcing_files(files, expected, deleted): 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 # Test that variables that have been modified are still there and contain
# the expected output # the expected output
@@ -394,7 +385,7 @@ def test_clear(env):
) )
def test_sanitize_literals(env, exclude, include): 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 # Check that all the included variables are there
assert all(x in after for x in include) 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): 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 in after for x in expected)
assert all(x not in after for x in deleted) 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", "before,after,search_list",
[ [
# Set environment variables # Set environment variables
({}, {"FOO": "foo"}, [environment.SetEnv("FOO", "foo")]), ({}, {"FOO": "foo"}, [envmod.SetEnv("FOO", "foo")]),
# Unset environment variables # Unset environment variables
({"FOO": "foo"}, {}, [environment.UnsetEnv("FOO")]), ({"FOO": "foo"}, {}, [envmod.UnsetEnv("FOO")]),
# Append paths to an environment variable # Append paths to an environment variable
( (
{"FOO_PATH": "/a/path"}, {"FOO_PATH": "/a/path"},
{"FOO_PATH": "/a/path:/b/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"}, {"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": "/a/path:/b/path"},
{"FOO_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:/b/path"},
{"FOO_PATH": "/a/path:/c/path"}, {"FOO_PATH": "/a/path:/c/path"},
[ [
environment.RemovePath("FOO_PATH", "/b/path"), envmod.RemovePath("FOO_PATH", "/b/path"),
environment.AppendPath("FOO_PATH", "/c/path"), envmod.AppendPath("FOO_PATH", "/c/path"),
], ],
), ),
( (
{"FOO_PATH": "/a/path:/b/path"}, {"FOO_PATH": "/a/path:/b/path"},
{"FOO_PATH": "/c/path:/a/path"}, {"FOO_PATH": "/c/path:/a/path"},
[ [
environment.RemovePath("FOO_PATH", "/b/path"), envmod.RemovePath("FOO_PATH", "/b/path"),
environment.PrependPath("FOO_PATH", "/c/path"), envmod.PrependPath("FOO_PATH", "/c/path"),
], ],
), ),
# Modify two variables in the same environment # 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": "foo", "BAR": "bar"},
{"FOO": "baz", "BAR": "baz"}, {"FOO": "baz", "BAR": "baz"},
[ [
environment.SetEnv("FOO", "baz"), envmod.SetEnv("FOO", "baz"),
environment.SetEnv("BAR", "baz"), envmod.SetEnv("BAR", "baz"),
], ],
), ),
], ],
) )
def test_from_environment_diff(before, after, search_list): 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: for item in search_list:
assert item in mod assert item in mod
@@ -501,7 +492,7 @@ def test_from_environment_diff(before, after, search_list):
def test_exclude_lmod_variables(): def test_exclude_lmod_variables():
# Construct the list of environment modifications # Construct the list of environment modifications
file = os.path.join(datadir, "sourceme_lmod.sh") 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 # Check that variables related to lmod are not in there
modifications = env.group_by_name() modifications = env.group_by_name()

View File

@@ -8,6 +8,7 @@
import pytest import pytest
from llnl.util.executable import which
from llnl.util.filesystem import mkdirp, touch, working_dir from llnl.util.filesystem import mkdirp, touch, working_dir
import spack.config import spack.config
@@ -15,7 +16,6 @@
from spack.fetch_strategy import HgFetchStrategy from spack.fetch_strategy import HgFetchStrategy
from spack.spec import Spec from spack.spec import Spec
from spack.stage import Stage from spack.stage import Stage
from spack.util.executable import which
from spack.version import ver from spack.version import ver
# Test functionality covered is supported on Windows, but currently failing # Test functionality covered is supported on Windows, but currently failing

View File

@@ -9,13 +9,13 @@
import pytest import pytest
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
from llnl.util.executable import Executable
import spack.platforms import spack.platforms
from spack.hooks.absolutify_elf_sonames import ( from spack.hooks.absolutify_elf_sonames import (
SharedLibrariesVisitor, SharedLibrariesVisitor,
find_and_patch_sonames, find_and_patch_sonames,
) )
from spack.util.executable import Executable
def skip_unless_linux(f): def skip_unless_linux(f):

View 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

View 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")

View File

@@ -3,7 +3,7 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack.util.string import plural from llnl.util.string import plural
def test_plural(): def test_plural():

View File

@@ -19,8 +19,7 @@
import llnl.util.lang as lang import llnl.util.lang as lang
import llnl.util.tty.log as log import llnl.util.tty.log as log
import llnl.util.tty.pty as pty import llnl.util.tty.pty as pty
from llnl.util.executable import which
from spack.util.executable import which
termios: Optional[ModuleType] = None termios: Optional[ModuleType] = None
try: try:

View File

@@ -7,10 +7,10 @@
import pytest import pytest
import llnl.util.executable as exe
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import spack.paths import spack.paths
import spack.util.executable as exe
import spack.util.git import spack.util.git
from spack.main import get_version, main from spack.main import get_version, main

View File

@@ -16,8 +16,9 @@
import pytest import pytest
from llnl.util.envmod import path_put_first
from spack.build_environment import MakeExecutable from spack.build_environment import MakeExecutable
from spack.util.environment import path_put_first
pytestmark = pytest.mark.skipif( pytestmark = pytest.mark.skipif(
sys.platform == "win32", sys.platform == "win32",

View File

@@ -9,16 +9,15 @@
import pytest import pytest
from llnl.util.executable import which
from llnl.util.filesystem import resolve_link_target_relative_to_the_link from llnl.util.filesystem import resolve_link_target_relative_to_the_link
import spack.mirror import spack.mirror
import spack.repo import spack.repo
import spack.util.executable
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
import spack.util.url as url_util import spack.util.url as url_util
from spack.spec import Spec from spack.spec import Spec
from spack.stage import Stage from spack.stage import Stage
from spack.util.executable import which
from spack.util.spack_yaml import SpackYAMLError from spack.util.spack_yaml import SpackYAMLError
pytestmark = [ pytestmark = [

Some files were not shown because too many files have changed in this diff Show More