Repository: spack/spack

Issue:
-variant syntax no longer works
I discovered this bug yesterday during the Spack Tutorial in front of 25-30 potential new users of Spack (kind of embarrassing). I can run `spack spec hdf5~mpi`, but if I run:
```
$ spack spec hdf5 -mpi
usage: spack [-h] [-d] [-D] [-k] [-m] [-p] [-P STAT] [--lines LINES] [-v] [-s]
             [-V]
             [COMMAND]
spack: error: argument -p/--profile: ignored explicit argument 'i'
```
or
```
$ spack install hdf5 -mpi
usage: spack [-h] [-d] [-D] [-k] [-m] [-p] [-P STAT] [--lines LINES] [-v] [-s]
             [-V]
             [COMMAND]
spack: error: argument -p/--profile: ignored explicit argument 'i'
```
it looks like the `-variant` syntax no longer works. Based on the error message, it looks like a bug in our argparse usage.


Discussion:

Resolving patch:
diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py
--- a/lib/spack/spack/main.py
+++ b/lib/spack/spack/main.py
@@ -32,8 +32,8 @@
 import sys
 import os
 import inspect
-from argparse import _ArgumentGroup, ArgumentParser, RawTextHelpFormatter
 import pstats
+import argparse
 
 import llnl.util.tty as tty
 from llnl.util.tty.color import *
@@ -126,7 +126,7 @@ def index_commands():
     return index
 
 
-class SpackArgumentParser(ArgumentParser):
+class SpackArgumentParser(argparse.ArgumentParser):
     def format_help_sections(self, level):
         """Format help on sections for a particular verbosity level.
 
@@ -165,7 +165,7 @@ def add_subcommand_group(title, commands):
                         if action.metavar in cmd_set)
 
             # add commands to a group in order, and add the group
-            group = _ArgumentGroup(self, title=title)
+            group = argparse._ArgumentGroup(self, title=title)
             for name in commands:
                 group._add_action(cmds[name])
                 if name in remaining:
@@ -265,7 +265,7 @@ def format_help(self, level='short'):
 def make_argument_parser():
     """Create an basic argument parser without any subcommands added."""
     parser = SpackArgumentParser(
-        formatter_class=RawTextHelpFormatter, add_help=False,
+        formatter_class=argparse.RawTextHelpFormatter, add_help=False,
         description=(
             "A flexible package manager that supports multiple versions,\n"
             "configurations, platforms, and compilers."))
@@ -410,8 +410,7 @@ def main(argv=None):
     # avoid loading all the modules from spack.cmd when we don't need
     # them, which reduces startup latency.
     parser = make_argument_parser()
-    parser.add_argument(
-        'command', metavar='COMMAND', nargs='?', action='store')
+    parser.add_argument('command', nargs=argparse.REMAINDER)
     args, unknown = parser.parse_known_args(argv)
 
     # Just print help and exit if run with no arguments at all
@@ -432,13 +431,13 @@ def main(argv=None):
 
     # Try to load the particular command the caller asked for.  If there
     # is no module for it, just die.
-    command_name = args.command.replace('-', '_')
+    command_name = args.command[0].replace('-', '_')
     try:
         parser.add_command(command_name)
     except ImportError:
         if spack.debug:
             raise
-        tty.die("Unknown command: %s" % args.command)
+        tty.die("Unknown command: %s" % args.command[0])
 
     # Re-parse with the proper sub-parser added.
     args, unknown = parser.parse_known_args()


Test patch:
diff --git a/lib/spack/spack/test/cmd/flake8.py b/lib/spack/spack/test/cmd/flake8.py
--- a/lib/spack/spack/test/cmd/flake8.py
+++ b/lib/spack/spack/test/cmd/flake8.py
@@ -81,6 +81,7 @@ def test_changed_files(parser, flake8_package):
     sys.version_info[:2] <= (2, 6) or
     (3, 0) <= sys.version_info[:2] <= (3, 3),
     reason='flake8 no longer supports Python 2.6 or 3.3 and older')
+@pytest.mark.skipif(not which('flake8'), reason='flake8 is not installed.')
 def test_flake8(parser, flake8_package):
     # Only test the flake8_package that we modified
     # Otherwise, the unit tests would fail every time