Fix issue with color formatting regular expression. (#5171)

- Fix issue with color formatting regular expression.
  - _separators regex in spec.py could be constructed such that '^' came
    first in the character matcher, e.g. '[^@#/]'.  This inverts the match
    and causes transient KeyErrors.

  - Fixed to escape all characters in the constructed regex.

  - This bug comes up in Python3 due to its more randomized hash iteration
    order, but it could probably also happen in a Python 2 implementation.

- also clean up variable docstrings in spec.py
This commit is contained in:
Todd Gamblin 2017-08-20 15:34:35 -07:00 committed by GitHub
parent 99fb394ac1
commit e77c1a20c5

View file

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