Add spec architeccture, redo color output support.
This commit is contained in:
parent
ebc507dc6e
commit
157737efbe
5 changed files with 129 additions and 70 deletions
|
@ -61,7 +61,7 @@ def parse_specs(args):
|
||||||
return spack.spec.parse(" ".join(args))
|
return spack.spec.parse(" ".join(args))
|
||||||
|
|
||||||
except spack.parse.ParseError, e:
|
except spack.parse.ParseError, e:
|
||||||
e.print_error(sys.stdout)
|
tty.error(e.message, e.string, e.pos * " " + "^")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
except spack.spec.SpecError, e:
|
except spack.spec.SpecError, e:
|
||||||
|
|
|
@ -24,10 +24,10 @@ def test(parser, args):
|
||||||
spack.test.run(name, verbose=args.verbose)
|
spack.test.run(name, verbose=args.verbose)
|
||||||
|
|
||||||
elif not args.names:
|
elif not args.names:
|
||||||
print parser._subparsers
|
|
||||||
print "Available tests:"
|
print "Available tests:"
|
||||||
colify(list_modules(spack.test_path))
|
colify(list_modules(spack.test_path))
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for name in args.names:
|
for name in args.names:
|
||||||
spack.test.run(name, verbose=args.verbose)
|
spack.test.run(name, verbose=args.verbose)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import re
|
import re
|
||||||
import spack.error as err
|
import spack.error as err
|
||||||
import spack.tty as tty
|
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,9 +10,6 @@ def __init__(self, message, string, pos):
|
||||||
self.string = string
|
self.string = string
|
||||||
self.pos = pos
|
self.pos = pos
|
||||||
|
|
||||||
def print_error(self, out):
|
|
||||||
tty.error(self.message, self.string, self.pos * " " + "^")
|
|
||||||
|
|
||||||
|
|
||||||
class LexError(ParseError):
|
class LexError(ParseError):
|
||||||
"""Raised when we don't know how to lex something."""
|
"""Raised when we don't know how to lex something."""
|
||||||
|
|
|
@ -42,8 +42,10 @@
|
||||||
spec-list = { spec [ dep-list ] }
|
spec-list = { spec [ dep-list ] }
|
||||||
dep_list = { ^ spec }
|
dep_list = { ^ spec }
|
||||||
spec = id [ options ]
|
spec = id [ options ]
|
||||||
options = { @version-list | +variant | -variant | ~variant | %compiler }
|
options = { @version-list | +variant | -variant | ~variant |
|
||||||
|
%compiler | =architecture }
|
||||||
variant = id
|
variant = id
|
||||||
|
architecture = id
|
||||||
compiler = id [ version-list ]
|
compiler = id [ version-list ]
|
||||||
version-list = version [ { , version } ]
|
version-list = version [ { , version } ]
|
||||||
version = id | id: | :id | id:id
|
version = id | id: | :id | id:id
|
||||||
|
@ -59,11 +61,22 @@
|
||||||
specs to avoid ambiguity. Both are provided because ~ can cause shell
|
specs to avoid ambiguity. Both are provided because ~ can cause shell
|
||||||
expansion when it is the first character in an id typed on the command line.
|
expansion when it is the first character in an id typed on the command line.
|
||||||
"""
|
"""
|
||||||
|
import sys
|
||||||
from functools import total_ordering
|
from functools import total_ordering
|
||||||
|
from StringIO import StringIO
|
||||||
|
|
||||||
|
import tty
|
||||||
import spack.parse
|
import spack.parse
|
||||||
from spack.version import Version, VersionRange
|
|
||||||
import spack.error
|
import spack.error
|
||||||
|
from spack.version import Version, VersionRange
|
||||||
|
from spack.color import ColorStream
|
||||||
|
|
||||||
|
# Color formats for various parts of specs when using color output.
|
||||||
|
compiler_fmt = '@g'
|
||||||
|
version_fmt = '@c'
|
||||||
|
architecture_fmt = '@m'
|
||||||
|
variant_enabled_fmt = '@B'
|
||||||
|
variant_disabled_fmt = '@r'
|
||||||
|
|
||||||
|
|
||||||
class SpecError(spack.error.SpackError):
|
class SpecError(spack.error.SpackError):
|
||||||
|
@ -86,6 +99,11 @@ class DuplicateCompilerError(SpecError):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
super(DuplicateCompilerError, self).__init__(message)
|
super(DuplicateCompilerError, self).__init__(message)
|
||||||
|
|
||||||
|
class DuplicateArchitectureError(SpecError):
|
||||||
|
"""Raised when the same architecture occurs in a spec twice."""
|
||||||
|
def __init__(self, message):
|
||||||
|
super(DuplicateArchitectureError, self).__init__(message)
|
||||||
|
|
||||||
|
|
||||||
class Compiler(object):
|
class Compiler(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
|
@ -95,19 +113,28 @@ def __init__(self, name):
|
||||||
def add_version(self, version):
|
def add_version(self, version):
|
||||||
self.versions.append(version)
|
self.versions.append(version)
|
||||||
|
|
||||||
def __str__(self):
|
def stringify(self, **kwargs):
|
||||||
out = "%%%s" % self.name
|
color = kwargs.get("color", False)
|
||||||
|
|
||||||
|
out = StringIO()
|
||||||
|
out.write("%s{%%%s}" % (compiler_fmt, self.name))
|
||||||
|
|
||||||
if self.versions:
|
if self.versions:
|
||||||
vlist = ",".join(str(v) for v in sorted(self.versions))
|
vlist = ",".join(str(v) for v in sorted(self.versions))
|
||||||
out += "@%s" % vlist
|
out.write("%s{@%s}" % (compiler_fmt, vlist))
|
||||||
return out
|
return out.getvalue()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.stringify()
|
||||||
|
|
||||||
|
|
||||||
class Spec(object):
|
class Spec(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self._package = None
|
||||||
self.versions = []
|
self.versions = []
|
||||||
self.variants = {}
|
self.variants = {}
|
||||||
|
self.architecture = None
|
||||||
self.compiler = None
|
self.compiler = None
|
||||||
self.dependencies = {}
|
self.dependencies = {}
|
||||||
|
|
||||||
|
@ -124,37 +151,76 @@ def add_compiler(self, compiler):
|
||||||
"Spec for '%s' cannot have two compilers." % self.name)
|
"Spec for '%s' cannot have two compilers." % self.name)
|
||||||
self.compiler = compiler
|
self.compiler = compiler
|
||||||
|
|
||||||
|
def add_architecture(self, architecture):
|
||||||
|
if self.architecture: raise DuplicateArchitectureError(
|
||||||
|
"Spec for '%s' cannot have two architectures." % self.name)
|
||||||
|
self.architecture = architecture
|
||||||
|
|
||||||
def add_dependency(self, dep):
|
def add_dependency(self, dep):
|
||||||
if dep.name in self.dependencies:
|
if dep.name in self.dependencies:
|
||||||
raise DuplicateDependencyError("Cannot depend on '%s' twice" % dep)
|
raise DuplicateDependencyError("Cannot depend on '%s' twice" % dep)
|
||||||
self.dependencies[dep.name] = dep
|
self.dependencies[dep.name] = dep
|
||||||
|
|
||||||
def __str__(self):
|
def canonicalize(self):
|
||||||
out = self.name
|
"""Ensures that the spec is in canonical form.
|
||||||
|
|
||||||
|
This means:
|
||||||
|
1. All dependencies of this package and of its dependencies are
|
||||||
|
in the dependencies list (transitive closure of deps).
|
||||||
|
2. All dependencies in the dependencies list are canonicalized.
|
||||||
|
|
||||||
|
This function also serves to validate the spec, in that it makes sure
|
||||||
|
that each package exists an that spec criteria don't violate package
|
||||||
|
criteria.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def package(self):
|
||||||
|
if self._package == None:
|
||||||
|
self._package = packages.get(self.name)
|
||||||
|
return self._package
|
||||||
|
|
||||||
|
def stringify(self, **kwargs):
|
||||||
|
color = kwargs.get("color", False)
|
||||||
|
|
||||||
|
out = ColorStream(StringIO(), color)
|
||||||
|
out.write("%s" % self.name)
|
||||||
|
|
||||||
if self.versions:
|
if self.versions:
|
||||||
vlist = ",".join(str(v) for v in sorted(self.versions))
|
vlist = ",".join(str(v) for v in sorted(self.versions))
|
||||||
out += "@%s" % vlist
|
out.write("%s{@%s}" % (version_fmt, vlist))
|
||||||
|
|
||||||
if self.compiler:
|
if self.compiler:
|
||||||
out += str(self.compiler)
|
out.write(self.compiler.stringify(color=color))
|
||||||
|
|
||||||
for name in sorted(self.variants.keys()):
|
for name in sorted(self.variants.keys()):
|
||||||
enabled = self.variants[name]
|
enabled = self.variants[name]
|
||||||
if enabled:
|
if enabled:
|
||||||
out += '+%s' % name
|
out.write('%s{+%s}' % (variant_enabled_fmt, name))
|
||||||
else:
|
else:
|
||||||
out += '~%s' % name
|
out.write('%s{~%s}' % (variant_disabled_fmt, name))
|
||||||
|
|
||||||
|
if self.architecture:
|
||||||
|
out.write("%s{=%s}" % (architecture_fmt, self.architecture))
|
||||||
|
|
||||||
for name in sorted(self.dependencies.keys()):
|
for name in sorted(self.dependencies.keys()):
|
||||||
out += " ^%s" % str(self.dependencies[name])
|
dep = " ^" + self.dependencies[name].stringify(color=color)
|
||||||
|
out.write(dep, raw=True)
|
||||||
|
|
||||||
return out
|
return out.getvalue()
|
||||||
|
|
||||||
|
def write(self, stream=sys.stdout):
|
||||||
|
isatty = stream.isatty()
|
||||||
|
stream.write(self.stringify(color=isatty))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.stringify()
|
||||||
|
|
||||||
#
|
#
|
||||||
# These are possible token types in the spec grammar.
|
# These are possible token types in the spec grammar.
|
||||||
#
|
#
|
||||||
DEP, AT, COLON, COMMA, ON, OFF, PCT, ID = range(8)
|
DEP, AT, COLON, COMMA, ON, OFF, PCT, EQ, ID = range(9)
|
||||||
|
|
||||||
class SpecLexer(spack.parse.Lexer):
|
class SpecLexer(spack.parse.Lexer):
|
||||||
"""Parses tokens that make up spack specs."""
|
"""Parses tokens that make up spack specs."""
|
||||||
|
@ -168,6 +234,7 @@ def __init__(self):
|
||||||
(r'\-', lambda scanner, val: self.token(OFF, val)),
|
(r'\-', lambda scanner, val: self.token(OFF, val)),
|
||||||
(r'\~', lambda scanner, val: self.token(OFF, val)),
|
(r'\~', lambda scanner, val: self.token(OFF, val)),
|
||||||
(r'\%', lambda scanner, val: self.token(PCT, val)),
|
(r'\%', lambda scanner, val: self.token(PCT, val)),
|
||||||
|
(r'\=', lambda scanner, val: self.token(EQ, val)),
|
||||||
(r'\w[\w.-]*', lambda scanner, val: self.token(ID, val)),
|
(r'\w[\w.-]*', lambda scanner, val: self.token(ID, val)),
|
||||||
(r'\s+', lambda scanner, val: None)])
|
(r'\s+', lambda scanner, val: None)])
|
||||||
|
|
||||||
|
@ -206,24 +273,35 @@ def spec(self):
|
||||||
spec.add_version(version)
|
spec.add_version(version)
|
||||||
|
|
||||||
elif self.accept(ON):
|
elif self.accept(ON):
|
||||||
self.expect(ID)
|
spec.add_variant(self.variant(), True)
|
||||||
self.check_identifier()
|
|
||||||
spec.add_variant(self.token.value, True)
|
|
||||||
|
|
||||||
elif self.accept(OFF):
|
elif self.accept(OFF):
|
||||||
self.expect(ID)
|
spec.add_variant(self.variant(), False)
|
||||||
self.check_identifier()
|
|
||||||
spec.add_variant(self.token.value, False)
|
|
||||||
|
|
||||||
elif self.accept(PCT):
|
elif self.accept(PCT):
|
||||||
spec.add_compiler(self.compiler())
|
spec.add_compiler(self.compiler())
|
||||||
|
|
||||||
|
elif self.accept(EQ):
|
||||||
|
spec.add_architecture(self.architecture())
|
||||||
|
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
return spec
|
return spec
|
||||||
|
|
||||||
|
|
||||||
|
def variant(self):
|
||||||
|
self.expect(ID)
|
||||||
|
self.check_identifier()
|
||||||
|
return self.token.value
|
||||||
|
|
||||||
|
|
||||||
|
def architecture(self):
|
||||||
|
self.expect(ID)
|
||||||
|
self.check_identifier()
|
||||||
|
return self.token.value
|
||||||
|
|
||||||
|
|
||||||
def version(self):
|
def version(self):
|
||||||
start = None
|
start = None
|
||||||
end = None
|
end = None
|
||||||
|
|
|
@ -1,61 +1,46 @@
|
||||||
import sys
|
import sys
|
||||||
import spack
|
import spack
|
||||||
|
from spack.color import cprint
|
||||||
|
|
||||||
indent = " "
|
indent = " "
|
||||||
|
|
||||||
def escape(s):
|
def msg(message, *args):
|
||||||
"""Returns a TTY escape code if stdout is a tty, otherwise empty string"""
|
cprint("@*b{==>} @*w{%s}" % str(message))
|
||||||
if sys.stdout.isatty():
|
for arg in args:
|
||||||
return "\033[{}m".format(s)
|
print indent + str(arg)
|
||||||
return ''
|
|
||||||
|
|
||||||
def color(n):
|
|
||||||
return escape("0;{}".format(n))
|
|
||||||
|
|
||||||
def bold(n):
|
def info(message, *args, **kwargs):
|
||||||
return escape("1;{}".format(n))
|
format = kwargs.get('format', '*b')
|
||||||
|
cprint("@%s{==>} %s" % (format, str(message)))
|
||||||
|
for arg in args:
|
||||||
|
print indent + str(arg)
|
||||||
|
|
||||||
def underline(n):
|
|
||||||
return escape("4;{}".format(n))
|
|
||||||
|
|
||||||
blue = bold(34)
|
def verbose(message, *args):
|
||||||
white = bold(39)
|
if spack.verbose:
|
||||||
red = bold(31)
|
info(message, *args, format='*g')
|
||||||
yellow = underline(33)
|
|
||||||
green = bold(92)
|
|
||||||
gray = bold(30)
|
|
||||||
em = underline(39)
|
|
||||||
reset = escape(0)
|
|
||||||
|
|
||||||
def msg(msg, *args, **kwargs):
|
|
||||||
color = kwargs.get("color", blue)
|
|
||||||
print "{}==>{} {}{}".format(color, white, str(msg), reset)
|
|
||||||
for arg in args: print indent + str(arg)
|
|
||||||
|
|
||||||
def info(msg, *args, **kwargs):
|
|
||||||
color = kwargs.get("color", blue)
|
|
||||||
print "{}==>{} {}".format(color, reset, str(msg))
|
|
||||||
for arg in args: print indent + str(arg)
|
|
||||||
|
|
||||||
def verbose(msg, *args):
|
|
||||||
if spack.verbose: info(msg, *args, color=green)
|
|
||||||
|
|
||||||
def debug(*args):
|
def debug(*args):
|
||||||
if spack.debug: msg(*args, color=red)
|
if spack.debug:
|
||||||
|
info(message, *args, format='*c')
|
||||||
|
|
||||||
def error(msg, *args):
|
|
||||||
print "{}Error{}: {}".format(red, reset, str(msg))
|
|
||||||
for arg in args: print indent + str(arg)
|
|
||||||
|
|
||||||
def warn(msg, *args):
|
def error(message, *args):
|
||||||
print "{}Warning{}: {}".format(yellow, reset, str(msg))
|
info(message, *args, format='*r')
|
||||||
for arg in args: print indent + str(arg)
|
|
||||||
|
|
||||||
def die(msg, *args):
|
|
||||||
error(msg, *args)
|
def warn(message, *args):
|
||||||
|
info(message, *args, format='*Y')
|
||||||
|
|
||||||
|
|
||||||
|
def die(message, *args):
|
||||||
|
error(message, *args)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def pkg(msg):
|
|
||||||
|
def pkg(message):
|
||||||
"""Outputs a message with a package icon."""
|
"""Outputs a message with a package icon."""
|
||||||
import platform
|
import platform
|
||||||
from version import Version
|
from version import Version
|
||||||
|
@ -64,5 +49,5 @@ def pkg(msg):
|
||||||
if mac_ver and Version(mac_ver) >= Version('10.7'):
|
if mac_ver and Version(mac_ver) >= Version('10.7'):
|
||||||
print u"\U0001F4E6" + indent,
|
print u"\U0001F4E6" + indent,
|
||||||
else:
|
else:
|
||||||
print '{}[+]{} '.format(green, reset),
|
cprint('@*g{[+]} ')
|
||||||
print msg
|
print message
|
||||||
|
|
Loading…
Reference in a new issue