Repository: spack/spack

Issue:
spack info: Spurious failures on Travis
Travis is failing spuriously when trying to execute:
```python
spack info openmpi
```
during unit tests. The stacktrace we get back is something like:
```
__________________________ test_it_just_runs[openmpi] __________________________
pkg = 'openmpi'
    @pytest.mark.parametrize('pkg', [
        'openmpi',
        'trilinos',
        'boost',
        'python',
        'dealii'
    ])
    def test_it_just_runs(pkg):
>       info(pkg)
../../../lib/spack/spack/test/cmd/info.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../lib/spack/spack/main.py:406: in __call__
    self.command, self.parser, args, unknown)
../../../lib/spack/spack/main.py:355: in _invoke_spack_command
    return_val = command(parser, args)
../../../lib/spack/spack/cmd/info.py:241: in info
    print_text_info(pkg)
../../../lib/spack/spack/cmd/info.py:231: in print_text_info
    when.colorized(), ', '.join(s.colorized() for s in specs)
../../../lib/spack/spack/spec.py:2670: in colorized
    return colorize_spec(self)
../../../lib/spack/spack/spec.py:240: in colorize_spec
    return colorize(re.sub(_separators, insert_color(), str(spec)) + '@.')
/home/travis/virtualenv/python3.5.3/lib/python3.5/re.py:182: in sub
    return _compile(pattern, flags).sub(repl, string, count)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <spack.spec.colorize_spec.<locals>.insert_color object at 0x7fd970749550>
match = <_sre.SRE_Match object; span=(0, 1), match='o'>
    def __call__(self, match):
        # ignore compiler versions (color same as compiler)
        sep = match.group(0)
        if self.last == '%' and sep == '@':
            return cescape(sep)
        self.last = sep
    
>       return '%s%s' % (color_formats[sep], cescape(sep))
E       KeyError: 'o'
../../../lib/spack/spack/spec.py:238: KeyError
```
The problem first occurred in #4994, and after trying without success to reproduce the issue both on Travis and locally I discarded it as some strange environment problem (like the ones we get from time to time regarding `svn` failing). Unfortunately, it happened again when building on `develop` [in build 12355](https://travis-ci.org/LLNL/spack/builds/265784067). Restarting the two failing builds made the issue disappear.


Discussion:
Can somebody create a `travis` tag to attach to this issue?
Happened to me in #5148 -- closed and reopened the PR and it tested ok.
@hartzell I'll try to understand what causes `sep == o` sometimes (even though it's difficult without a reproducer). Regarding closing and reopening: I don't know if you have permissions to do that, but from the Travis interface you can restart just the single job that failed. In case just ping me or @adamjstewart if you want to avoid waiting for the 50 min. build of `hypre` a second time.
There are a lot of other spurious Travis failures that I would love to get to the bottom of (`python != generic`, SVN tests, etc). If you ever figure those out, let me know. I just saw another `python != generic` yesterday.

Resolving patch:
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -165,21 +165,20 @@
     'NoSuchHashError',
     'RedundantSpecError']
 
-# Valid pattern for an identifier in Spack
+#: Valid pattern for an identifier in Spack
 identifier_re = r'\w[\w-]*'
 
-# Convenient names for color formats so that other things can use them
-compiler_color = '@g'
-version_color = '@c'
-architecture_color = '@m'
-enabled_variant_color = '@B'
-disabled_variant_color = '@r'
-dependency_color = '@.'
-hash_color = '@K'
-
-"""This map determines the coloring of specs when using color output.
-   We make the fields different colors to enhance readability.
-   See spack.color for descriptions of the color codes. """
+compiler_color = '@g'          #: color for highlighting compilers
+version_color = '@c'           #: color for highlighting versions
+architecture_color = '@m'      #: color for highlighting architectures
+enabled_variant_color = '@B'   #: color for highlighting enabled variants
+disabled_variant_color = '@r'  #: color for highlighting disabled varaints
+dependency_color = '@.'        #: color for highlighting dependencies
+hash_color = '@K'              #: color for highlighting package hashes
+
+#: This map determines the coloring of specs when using color output.
+#: We make the fields different colors to enhance readability.
+#: See spack.color for descriptions of the color codes.
 color_formats = {'%': compiler_color,
                  '@': version_color,
                  '=': architecture_color,
@@ -188,17 +187,19 @@
                  '^': dependency_color,
                  '#': hash_color}
 
-"""Regex used for splitting by spec field separators."""
-_separators = '[%s]' % ''.join(color_formats.keys())
+#: Regex used for splitting by spec field separators.
+#: These need to be escaped to avoid metacharacters in
+#: ``color_formats.keys()``.
+_separators = '[\\%s]' % '\\'.join(color_formats.keys())
 
-"""Versionlist constant so we don't have to build a list
-   every time we call str()"""
+#: Versionlist constant so we don't have to build a list
+#: every time we call str()
 _any_version = VersionList([':'])
 
-"""Types of dependencies that Spack understands."""
+#: Types of dependencies that Spack understands.
 alldeps = ('build', 'link', 'run')
 
-"""Max integer helps avoid passing too large a value to cyaml."""
+#: Max integer helps avoid passing too large a value to cyaml.
 maxint = 2 ** (ctypes.sizeof(ctypes.c_int) * 8 - 1) - 1
 
 


Test patch: