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))
|
||||
|
||||
except spack.parse.ParseError, e:
|
||||
e.print_error(sys.stdout)
|
||||
tty.error(e.message, e.string, e.pos * " " + "^")
|
||||
sys.exit(1)
|
||||
|
||||
except spack.spec.SpecError, e:
|
||||
|
|
|
@ -24,10 +24,10 @@ def test(parser, args):
|
|||
spack.test.run(name, verbose=args.verbose)
|
||||
|
||||
elif not args.names:
|
||||
print parser._subparsers
|
||||
print "Available tests:"
|
||||
colify(list_modules(spack.test_path))
|
||||
|
||||
|
||||
else:
|
||||
for name in args.names:
|
||||
spack.test.run(name, verbose=args.verbose)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import re
|
||||
import spack.error as err
|
||||
import spack.tty as tty
|
||||
import itertools
|
||||
|
||||
|
||||
|
@ -11,9 +10,6 @@ def __init__(self, message, string, pos):
|
|||
self.string = string
|
||||
self.pos = pos
|
||||
|
||||
def print_error(self, out):
|
||||
tty.error(self.message, self.string, self.pos * " " + "^")
|
||||
|
||||
|
||||
class LexError(ParseError):
|
||||
"""Raised when we don't know how to lex something."""
|
||||
|
|
|
@ -42,8 +42,10 @@
|
|||
spec-list = { spec [ dep-list ] }
|
||||
dep_list = { ^ spec }
|
||||
spec = id [ options ]
|
||||
options = { @version-list | +variant | -variant | ~variant | %compiler }
|
||||
options = { @version-list | +variant | -variant | ~variant |
|
||||
%compiler | =architecture }
|
||||
variant = id
|
||||
architecture = id
|
||||
compiler = id [ version-list ]
|
||||
version-list = version [ { , version } ]
|
||||
version = id | id: | :id | id:id
|
||||
|
@ -59,11 +61,22 @@
|
|||
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.
|
||||
"""
|
||||
import sys
|
||||
from functools import total_ordering
|
||||
from StringIO import StringIO
|
||||
|
||||
import tty
|
||||
import spack.parse
|
||||
from spack.version import Version, VersionRange
|
||||
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):
|
||||
|
@ -86,6 +99,11 @@ class DuplicateCompilerError(SpecError):
|
|||
def __init__(self, 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):
|
||||
def __init__(self, name):
|
||||
|
@ -95,19 +113,28 @@ def __init__(self, name):
|
|||
def add_version(self, version):
|
||||
self.versions.append(version)
|
||||
|
||||
def __str__(self):
|
||||
out = "%%%s" % self.name
|
||||
def stringify(self, **kwargs):
|
||||
color = kwargs.get("color", False)
|
||||
|
||||
out = StringIO()
|
||||
out.write("%s{%%%s}" % (compiler_fmt, self.name))
|
||||
|
||||
if self.versions:
|
||||
vlist = ",".join(str(v) for v in sorted(self.versions))
|
||||
out += "@%s" % vlist
|
||||
return out
|
||||
out.write("%s{@%s}" % (compiler_fmt, vlist))
|
||||
return out.getvalue()
|
||||
|
||||
def __str__(self):
|
||||
return self.stringify()
|
||||
|
||||
|
||||
class Spec(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self._package = None
|
||||
self.versions = []
|
||||
self.variants = {}
|
||||
self.architecture = None
|
||||
self.compiler = None
|
||||
self.dependencies = {}
|
||||
|
||||
|
@ -124,37 +151,76 @@ def add_compiler(self, compiler):
|
|||
"Spec for '%s' cannot have two compilers." % self.name)
|
||||
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):
|
||||
if dep.name in self.dependencies:
|
||||
raise DuplicateDependencyError("Cannot depend on '%s' twice" % dep)
|
||||
self.dependencies[dep.name] = dep
|
||||
|
||||
def __str__(self):
|
||||
out = self.name
|
||||
def canonicalize(self):
|
||||
"""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:
|
||||
vlist = ",".join(str(v) for v in sorted(self.versions))
|
||||
out += "@%s" % vlist
|
||||
out.write("%s{@%s}" % (version_fmt, vlist))
|
||||
|
||||
if self.compiler:
|
||||
out += str(self.compiler)
|
||||
out.write(self.compiler.stringify(color=color))
|
||||
|
||||
for name in sorted(self.variants.keys()):
|
||||
enabled = self.variants[name]
|
||||
if enabled:
|
||||
out += '+%s' % name
|
||||
out.write('%s{+%s}' % (variant_enabled_fmt, name))
|
||||
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()):
|
||||
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.
|
||||
#
|
||||
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):
|
||||
"""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(PCT, val)),
|
||||
(r'\=', lambda scanner, val: self.token(EQ, val)),
|
||||
(r'\w[\w.-]*', lambda scanner, val: self.token(ID, val)),
|
||||
(r'\s+', lambda scanner, val: None)])
|
||||
|
||||
|
@ -206,24 +273,35 @@ def spec(self):
|
|||
spec.add_version(version)
|
||||
|
||||
elif self.accept(ON):
|
||||
self.expect(ID)
|
||||
self.check_identifier()
|
||||
spec.add_variant(self.token.value, True)
|
||||
spec.add_variant(self.variant(), True)
|
||||
|
||||
elif self.accept(OFF):
|
||||
self.expect(ID)
|
||||
self.check_identifier()
|
||||
spec.add_variant(self.token.value, False)
|
||||
spec.add_variant(self.variant(), False)
|
||||
|
||||
elif self.accept(PCT):
|
||||
spec.add_compiler(self.compiler())
|
||||
|
||||
elif self.accept(EQ):
|
||||
spec.add_architecture(self.architecture())
|
||||
|
||||
else:
|
||||
break
|
||||
|
||||
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):
|
||||
start = None
|
||||
end = None
|
||||
|
|
|
@ -1,61 +1,46 @@
|
|||
import sys
|
||||
import spack
|
||||
from spack.color import cprint
|
||||
|
||||
indent = " "
|
||||
|
||||
def escape(s):
|
||||
"""Returns a TTY escape code if stdout is a tty, otherwise empty string"""
|
||||
if sys.stdout.isatty():
|
||||
return "\033[{}m".format(s)
|
||||
return ''
|
||||
def msg(message, *args):
|
||||
cprint("@*b{==>} @*w{%s}" % str(message))
|
||||
for arg in args:
|
||||
print indent + str(arg)
|
||||
|
||||
def color(n):
|
||||
return escape("0;{}".format(n))
|
||||
|
||||
def bold(n):
|
||||
return escape("1;{}".format(n))
|
||||
def info(message, *args, **kwargs):
|
||||
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)
|
||||
white = bold(39)
|
||||
red = bold(31)
|
||||
yellow = underline(33)
|
||||
green = bold(92)
|
||||
gray = bold(30)
|
||||
em = underline(39)
|
||||
reset = escape(0)
|
||||
def verbose(message, *args):
|
||||
if spack.verbose:
|
||||
info(message, *args, format='*g')
|
||||
|
||||
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):
|
||||
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):
|
||||
print "{}Warning{}: {}".format(yellow, reset, str(msg))
|
||||
for arg in args: print indent + str(arg)
|
||||
def error(message, *args):
|
||||
info(message, *args, format='*r')
|
||||
|
||||
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)
|
||||
|
||||
def pkg(msg):
|
||||
|
||||
def pkg(message):
|
||||
"""Outputs a message with a package icon."""
|
||||
import platform
|
||||
from version import Version
|
||||
|
@ -64,5 +49,5 @@ def pkg(msg):
|
|||
if mac_ver and Version(mac_ver) >= Version('10.7'):
|
||||
print u"\U0001F4E6" + indent,
|
||||
else:
|
||||
print '{}[+]{} '.format(green, reset),
|
||||
print msg
|
||||
cprint('@*g{[+]} ')
|
||||
print message
|
||||
|
|
Loading…
Reference in a new issue