SpackCommand objects can set global args (#22318)

This commit extends the API of the __call__ method of the
SpackCommand class to permit passing global arguments 
like those interposed between the main "spack" command 
and the subsequent subcommand.

The functionality is used to fix an issue where running

```spack -e . location -b some_package```

ends up printing the name of the environment instead of 
the build directory of the package, because the location arg 
parser also stores this value as `arg.env`.
This commit is contained in:
Harmen Stoppels 2021-03-30 18:47:36 +02:00 committed by GitHub
parent c3bab11ee1
commit b848fab3ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 5 deletions

View File

@ -56,7 +56,7 @@ def setup_parser(subparser):
help="build directory for a spec " help="build directory for a spec "
"(requires it to be staged first)") "(requires it to be staged first)")
directories.add_argument( directories.add_argument(
'-e', '--env', action='store', '-e', '--env', action='store', dest='location_env',
help="location of an environment managed by spack") help="location of an environment managed by spack")
arguments.add_common_arguments(subparser, ['spec']) arguments.add_common_arguments(subparser, ['spec'])
@ -71,10 +71,10 @@ def location(parser, args):
print(spack.paths.prefix) print(spack.paths.prefix)
return return
if args.env: if args.location_env:
path = spack.environment.root(args.env) path = spack.environment.root(args.location_env)
if not os.path.isdir(path): if not os.path.isdir(path):
tty.die("no such environment: '%s'" % args.env) tty.die("no such environment: '%s'" % args.location_env)
print(path) print(path)
return return

View File

@ -528,6 +528,8 @@ def __call__(self, *argv, **kwargs):
Keyword Args: Keyword Args:
fail_on_error (optional bool): Don't raise an exception on error fail_on_error (optional bool): Don't raise an exception on error
global_args (optional list): List of global spack arguments:
simulates ``spack [global_args] [command] [*argv]``
Returns: Returns:
(str): combined output and error as a string (str): combined output and error as a string
@ -540,8 +542,10 @@ def __call__(self, *argv, **kwargs):
self.returncode = None self.returncode = None
self.error = None self.error = None
prepend = kwargs['global_args'] if 'global_args' in kwargs else []
args, unknown = self.parser.parse_known_args( args, unknown = self.parser.parse_known_args(
[self.command_name] + list(argv)) prepend + [self.command_name] + list(argv))
fail_on_error = kwargs.get('fail_on_error', True) fail_on_error = kwargs.get('fail_on_error', True)

View File

@ -19,6 +19,7 @@
# location prints out "locations of packages and spack directories" # location prints out "locations of packages and spack directories"
location = SpackCommand('location') location = SpackCommand('location')
env = SpackCommand('env')
@pytest.fixture @pytest.fixture
@ -84,6 +85,27 @@ def test_location_env(mock_test_env):
assert location('--env', test_env_name).strip() == env_dir assert location('--env', test_env_name).strip() == env_dir
def test_location_env_flag_interference(mutable_mock_env_path, tmpdir):
"""
Tests that specifying an active environment using `spack -e x location ...`
does not interfere with the location command flags.
"""
# create two environments
env('create', 'first_env')
env('create', 'second_env')
global_args = ['-e', 'first_env']
# `spack -e first_env location -e second_env` should print the env
# path of second_env
assert 'first_env' not in location('-e', 'second_env', global_args=global_args)
# `spack -e first_env location --packages` should not print
# the environment path of first_env.
assert 'first_env' not in location('--packages', global_args=global_args)
def test_location_env_missing(): def test_location_env_missing():
"""Tests spack location --env.""" """Tests spack location --env."""
missing_env_name = 'missing-env' missing_env_name = 'missing-env'