qa : fixed flake8 issues

This commit is contained in:
alalazo 2016-06-08 16:33:49 +02:00
parent 4a61efe641
commit 564483936f
4 changed files with 64 additions and 107 deletions

View file

@ -43,16 +43,16 @@
intersection intersection
concrete concrete
""" """
import os
import sys
import re import re
from bisect import bisect_left from bisect import bisect_left
from functools import wraps from functools import wraps
from functools_backport import total_ordering from functools_backport import total_ordering
# Valid version characters # Valid version characters
VALID_VERSION = r'[A-Za-z0-9_.-]' VALID_VERSION = r'[A-Za-z0-9_.-]'
def int_if_int(string): def int_if_int(string):
"""Convert a string to int if possible. Otherwise, return a string.""" """Convert a string to int if possible. Otherwise, return a string."""
try: try:
@ -62,10 +62,11 @@ def int_if_int(string):
def coerce_versions(a, b): def coerce_versions(a, b):
"""Convert both a and b to the 'greatest' type between them, in this order: """
Convert both a and b to the 'greatest' type between them, in this order:
Version < VersionRange < VersionList Version < VersionRange < VersionList
This is used to simplify comparison operations below so that we're always This is used to simplify comparison operations below so that we're always
comparing things that are of the same type. comparing things that are of the same type.
""" """
order = (Version, VersionRange, VersionList) order = (Version, VersionRange, VersionList)
ta, tb = type(a), type(b) ta, tb = type(a), type(b)
@ -105,6 +106,7 @@ def coercing_method(a, b, *args, **kwargs):
@total_ordering @total_ordering
class Version(object): class Version(object):
"""Class to represent versions""" """Class to represent versions"""
def __init__(self, string): def __init__(self, string):
string = str(string) string = str(string)
@ -142,15 +144,12 @@ def up_to(self, index):
""" """
return '.'.join(str(x) for x in self[:index]) return '.'.join(str(x) for x in self[:index])
def lowest(self): def lowest(self):
return self return self
def highest(self): def highest(self):
return self return self
@coerced @coerced
def satisfies(self, other): def satisfies(self, other):
"""A Version 'satisfies' another if it is at least as specific and has a """A Version 'satisfies' another if it is at least as specific and has a
@ -158,11 +157,10 @@ def satisfies(self, other):
gcc@4.7 so that when a user asks to build with gcc@4.7, we can find gcc@4.7 so that when a user asks to build with gcc@4.7, we can find
a suitable compiler. a suitable compiler.
""" """
nself = len(self.version) nself = len(self.version)
nother = len(other.version) nother = len(other.version)
return nother <= nself and self.version[:nother] == other.version return nother <= nself and self.version[:nother] == other.version
def wildcard(self): def wildcard(self):
"""Create a regex that will match variants of this version string.""" """Create a regex that will match variants of this version string."""
def a_or_n(seg): def a_or_n(seg):
@ -192,28 +190,22 @@ def a_or_n(seg):
wc += '(?:[a-z]|alpha|beta)?)?' * (len(segments) - 1) wc += '(?:[a-z]|alpha|beta)?)?' * (len(segments) - 1)
return wc return wc
def __iter__(self): def __iter__(self):
return iter(self.version) return iter(self.version)
def __getitem__(self, idx): def __getitem__(self, idx):
return tuple(self.version[idx]) return tuple(self.version[idx])
def __repr__(self): def __repr__(self):
return self.string return self.string
def __str__(self): def __str__(self):
return self.string return self.string
@property @property
def concrete(self): def concrete(self):
return self return self
@coerced @coerced
def __lt__(self, other): def __lt__(self, other):
"""Version comparison is designed for consistency with the way RPM """Version comparison is designed for consistency with the way RPM
@ -246,28 +238,23 @@ def __lt__(self, other):
# If the common prefix is equal, the one with more segments is bigger. # If the common prefix is equal, the one with more segments is bigger.
return len(self.version) < len(other.version) return len(self.version) < len(other.version)
@coerced @coerced
def __eq__(self, other): def __eq__(self, other):
return (other is not None and return (other is not None and
type(other) == Version and self.version == other.version) type(other) == Version and self.version == other.version)
def __ne__(self, other): def __ne__(self, other):
return not (self == other) return not (self == other)
def __hash__(self): def __hash__(self):
return hash(self.version) return hash(self.version)
@coerced @coerced
def __contains__(self, other): def __contains__(self, other):
if other is None: if other is None:
return False return False
return other.version[:len(self.version)] == self.version return other.version[:len(self.version)] == self.version
def is_predecessor(self, other): def is_predecessor(self, other):
"""True if the other version is the immediate predecessor of this one. """True if the other version is the immediate predecessor of this one.
That is, NO versions v exist such that: That is, NO versions v exist such that:
@ -280,16 +267,13 @@ def is_predecessor(self, other):
ol = other.version[-1] ol = other.version[-1]
return type(sl) == int and type(ol) == int and (ol - sl == 1) return type(sl) == int and type(ol) == int and (ol - sl == 1)
def is_successor(self, other): def is_successor(self, other):
return other.is_predecessor(self) return other.is_predecessor(self)
@coerced @coerced
def overlaps(self, other): def overlaps(self, other):
return self in other or other in self return self in other or other in self
@coerced @coerced
def union(self, other): def union(self, other):
if self == other or other in self: if self == other or other in self:
@ -299,7 +283,6 @@ def union(self, other):
else: else:
return VersionList([self, other]) return VersionList([self, other])
@coerced @coerced
def intersection(self, other): def intersection(self, other):
if self == other: if self == other:
@ -310,6 +293,7 @@ def intersection(self, other):
@total_ordering @total_ordering
class VersionRange(object): class VersionRange(object):
def __init__(self, start, end): def __init__(self, start, end):
if isinstance(start, basestring): if isinstance(start, basestring):
start = Version(start) start = Version(start)
@ -321,15 +305,12 @@ def __init__(self, start, end):
if start and end and end < start: if start and end and end < start:
raise ValueError("Invalid Version range: %s" % self) raise ValueError("Invalid Version range: %s" % self)
def lowest(self): def lowest(self):
return self.start return self.start
def highest(self): def highest(self):
return self.end return self.end
@coerced @coerced
def __lt__(self, other): def __lt__(self, other):
"""Sort VersionRanges lexicographically so that they are ordered first """Sort VersionRanges lexicographically so that they are ordered first
@ -342,28 +323,24 @@ def __lt__(self, other):
s, o = self, other s, o = self, other
if s.start != o.start: if s.start != o.start:
return s.start is None or (o.start is not None and s.start < o.start) return s.start is None or (o.start is not None and s.start < o.start) # NOQA: ignore=E501
return (s.end != o.end and return (s.end != o.end and
o.end is None or (s.end is not None and s.end < o.end)) o.end is None or (s.end is not None and s.end < o.end))
@coerced @coerced
def __eq__(self, other): def __eq__(self, other):
return (other is not None and return (other is not None and
type(other) == VersionRange and type(other) == VersionRange and
self.start == other.start and self.end == other.end) self.start == other.start and self.end == other.end)
def __ne__(self, other): def __ne__(self, other):
return not (self == other) return not (self == other)
@property @property
def concrete(self): def concrete(self):
return self.start if self.start == self.end else None return self.start if self.start == self.end else None
@coerced @coerced
def __contains__(self, other): def __contains__(self, other):
if other is None: if other is None:
@ -384,57 +361,55 @@ def __contains__(self, other):
other.end in self.end))) other.end in self.end)))
return in_upper return in_upper
@coerced @coerced
def satisfies(self, other): def satisfies(self, other):
"""A VersionRange satisfies another if some version in this range """
would satisfy some version in the other range. To do this it must A VersionRange satisfies another if some version in this range
either: would satisfy some version in the other range. To do this it must
a) Overlap with the other range either:
b) The start of this range satisfies the end of the other range. a) Overlap with the other range
b) The start of this range satisfies the end of the other range.
This is essentially the same as overlaps(), but overlaps assumes This is essentially the same as overlaps(), but overlaps assumes
that its arguments are specific. That is, 4.7 is interpreted as that its arguments are specific. That is, 4.7 is interpreted as
4.7.0.0.0.0... . This funciton assumes that 4.7 woudl be satisfied 4.7.0.0.0.0... . This funciton assumes that 4.7 woudl be satisfied
by 4.7.3.5, etc. by 4.7.3.5, etc.
Rationale: Rationale:
If a user asks for gcc@4.5:4.7, and a package is only compatible with If a user asks for gcc@4.5:4.7, and a package is only compatible with
gcc@4.7.3:4.8, then that package should be able to build under the gcc@4.7.3:4.8, then that package should be able to build under the
constraints. Just using overlaps() would not work here. constraints. Just using overlaps() would not work here.
Note that we don't need to check whether the end of this range Note that we don't need to check whether the end of this range
would satisfy the start of the other range, because overlaps() would satisfy the start of the other range, because overlaps()
already covers that case. already covers that case.
Note further that overlaps() is a symmetric operation, while Note further that overlaps() is a symmetric operation, while
satisfies() is not. satisfies() is not.
""" """
return (self.overlaps(other) or return (self.overlaps(other) or
# if either self.start or other.end are None, then this can't # if either self.start or other.end are None, then this can't
# satisfy, or overlaps() would've taken care of it. # satisfy, or overlaps() would've taken care of it.
self.start and other.end and self.start.satisfies(other.end)) self.start and other.end and self.start.satisfies(other.end))
@coerced @coerced
def overlaps(self, other): def overlaps(self, other):
return ((self.start == None or other.end is None or return ((self.start is None or other.end is None or
self.start <= other.end or self.start <= other.end or
other.end in self.start or self.start in other.end) and other.end in self.start or self.start in other.end) and
(other.start is None or self.end == None or (other.start is None or self.end is None or
other.start <= self.end or other.start <= self.end or
other.start in self.end or self.end in other.start)) other.start in self.end or self.end in other.start))
@coerced @coerced
def union(self, other): def union(self, other):
if not self.overlaps(other): if not self.overlaps(other):
if (self.end is not None and other.start is not None and if (self.end is not None and other.start is not None and
self.end.is_predecessor(other.start)): self.end.is_predecessor(other.start)):
return VersionRange(self.start, other.end) return VersionRange(self.start, other.end)
if (other.end is not None and self.start is not None and if (other.end is not None and self.start is not None and
other.end.is_predecessor(self.start)): other.end.is_predecessor(self.start)):
return VersionRange(other.start, self.end) return VersionRange(other.start, self.end)
return VersionList([self, other]) return VersionList([self, other])
@ -453,13 +428,12 @@ def union(self, other):
else: else:
end = self.end end = self.end
# TODO: See note in intersection() about < and in discrepancy. # TODO: See note in intersection() about < and in discrepancy.
if not other.end in self.end: if other.end not in self.end:
if end in other.end or other.end > self.end: if end in other.end or other.end > self.end:
end = other.end end = other.end
return VersionRange(start, end) return VersionRange(start, end)
@coerced @coerced
def intersection(self, other): def intersection(self, other):
if self.overlaps(other): if self.overlaps(other):
@ -481,7 +455,7 @@ def intersection(self, other):
# 1.6 < 1.6.5 = True (lexicographic) # 1.6 < 1.6.5 = True (lexicographic)
# Should 1.6 NOT be less than 1.6.5? Hm. # Should 1.6 NOT be less than 1.6.5? Hm.
# Here we test (not end in other.end) first to avoid paradox. # Here we test (not end in other.end) first to avoid paradox.
if other.end is not None and not end in other.end: if other.end is not None and end not in other.end:
if other.end < end or other.end in end: if other.end < end or other.end in end:
end = other.end end = other.end
@ -490,15 +464,12 @@ def intersection(self, other):
else: else:
return VersionList() return VersionList()
def __hash__(self): def __hash__(self):
return hash((self.start, self.end)) return hash((self.start, self.end))
def __repr__(self): def __repr__(self):
return self.__str__() return self.__str__()
def __str__(self): def __str__(self):
out = "" out = ""
if self.start: if self.start:
@ -512,6 +483,7 @@ def __str__(self):
@total_ordering @total_ordering
class VersionList(object): class VersionList(object):
"""Sorted, non-redundant list of Versions and VersionRanges.""" """Sorted, non-redundant list of Versions and VersionRanges."""
def __init__(self, vlist=None): def __init__(self, vlist=None):
self.versions = [] self.versions = []
if vlist is not None: if vlist is not None:
@ -526,7 +498,6 @@ def __init__(self, vlist=None):
for v in vlist: for v in vlist:
self.add(ver(v)) self.add(ver(v))
def add(self, version): def add(self, version):
if type(version) in (Version, VersionRange): if type(version) in (Version, VersionRange):
# This normalizes single-value version ranges. # This normalizes single-value version ranges.
@ -535,9 +506,9 @@ def add(self, version):
i = bisect_left(self, version) i = bisect_left(self, version)
while i-1 >= 0 and version.overlaps(self[i-1]): while i - 1 >= 0 and version.overlaps(self[i - 1]):
version = version.union(self[i-1]) version = version.union(self[i - 1])
del self.versions[i-1] del self.versions[i - 1]
i -= 1 i -= 1
while i < len(self) and version.overlaps(self[i]): while i < len(self) and version.overlaps(self[i]):
@ -553,7 +524,6 @@ def add(self, version):
else: else:
raise TypeError("Can't add %s to VersionList" % type(version)) raise TypeError("Can't add %s to VersionList" % type(version))
@property @property
def concrete(self): def concrete(self):
if len(self) == 1: if len(self) == 1:
@ -561,11 +531,9 @@ def concrete(self):
else: else:
return None return None
def copy(self): def copy(self):
return VersionList(self) return VersionList(self)
def lowest(self): def lowest(self):
"""Get the lowest version in the list.""" """Get the lowest version in the list."""
if not self: if not self:
@ -573,7 +541,6 @@ def lowest(self):
else: else:
return self[0].lowest() return self[0].lowest()
def highest(self): def highest(self):
"""Get the highest version in the list.""" """Get the highest version in the list."""
if not self: if not self:
@ -581,7 +548,6 @@ def highest(self):
else: else:
return self[-1].highest() return self[-1].highest()
@coerced @coerced
def overlaps(self, other): def overlaps(self, other):
if not other or not self: if not other or not self:
@ -597,14 +563,12 @@ def overlaps(self, other):
o += 1 o += 1
return False return False
def to_dict(self): def to_dict(self):
"""Generate human-readable dict for YAML.""" """Generate human-readable dict for YAML."""
if self.concrete: if self.concrete:
return { 'version' : str(self[0]) } return {'version': str(self[0])}
else: else:
return { 'versions' : [str(v) for v in self] } return {'versions': [str(v) for v in self]}
@staticmethod @staticmethod
def from_dict(dictionary): def from_dict(dictionary):
@ -616,7 +580,6 @@ def from_dict(dictionary):
else: else:
raise ValueError("Dict must have 'version' or 'versions' in it.") raise ValueError("Dict must have 'version' or 'versions' in it.")
@coerced @coerced
def satisfies(self, other, strict=False): def satisfies(self, other, strict=False):
"""A VersionList satisfies another if some version in the list """A VersionList satisfies another if some version in the list
@ -644,20 +607,17 @@ def satisfies(self, other, strict=False):
o += 1 o += 1
return False return False
@coerced @coerced
def update(self, other): def update(self, other):
for v in other.versions: for v in other.versions:
self.add(v) self.add(v)
@coerced @coerced
def union(self, other): def union(self, other):
result = self.copy() result = self.copy()
result.update(other) result.update(other)
return result return result
@coerced @coerced
def intersection(self, other): def intersection(self, other):
# TODO: make this faster. This is O(n^2). # TODO: make this faster. This is O(n^2).
@ -667,7 +627,6 @@ def intersection(self, other):
result.add(s.intersection(o)) result.add(s.intersection(o))
return result return result
@coerced @coerced
def intersect(self, other): def intersect(self, other):
"""Intersect this spec's list with other. """Intersect this spec's list with other.
@ -689,50 +648,40 @@ def __contains__(self, other):
if i == 0: if i == 0:
if version not in self[0]: if version not in self[0]:
return False return False
elif all(version not in v for v in self[i-1:]): elif all(version not in v for v in self[i - 1:]):
return False return False
return True return True
def __getitem__(self, index): def __getitem__(self, index):
return self.versions[index] return self.versions[index]
def __iter__(self): def __iter__(self):
return iter(self.versions) return iter(self.versions)
def __reversed__(self): def __reversed__(self):
return reversed(self.versions) return reversed(self.versions)
def __len__(self): def __len__(self):
return len(self.versions) return len(self.versions)
@coerced @coerced
def __eq__(self, other): def __eq__(self, other):
return other is not None and self.versions == other.versions return other is not None and self.versions == other.versions
def __ne__(self, other): def __ne__(self, other):
return not (self == other) return not (self == other)
@coerced @coerced
def __lt__(self, other): def __lt__(self, other):
return other is not None and self.versions < other.versions return other is not None and self.versions < other.versions
def __hash__(self): def __hash__(self):
return hash(tuple(self.versions)) return hash(tuple(self.versions))
def __str__(self): def __str__(self):
return ",".join(str(v) for v in self.versions) return ",".join(str(v) for v in self.versions)
def __repr__(self): def __repr__(self):
return str(self.versions) return str(self.versions)
@ -741,7 +690,7 @@ def _string_to_version(string):
"""Converts a string to a Version, VersionList, or VersionRange. """Converts a string to a Version, VersionList, or VersionRange.
This is private. Client code should use ver(). This is private. Client code should use ver().
""" """
string = string.replace(' ','') string = string.replace(' ', '')
if ',' in string: if ',' in string:
return VersionList(string.split(',')) return VersionList(string.split(','))
@ -749,7 +698,7 @@ def _string_to_version(string):
elif ':' in string: elif ':' in string:
s, e = string.split(':') s, e = string.split(':')
start = Version(s) if s else None start = Version(s) if s else None
end = Version(e) if e else None end = Version(e) if e else None
return VersionRange(start, end) return VersionRange(start, end)
else: else:

View file

@ -34,7 +34,7 @@ class Lmod(Package):
variable. Modulefiles for Library packages provide environment variables variable. Modulefiles for Library packages provide environment variables
that specify where the library and header files can be found. that specify where the library and header files can be found.
""" """
homepage = 'https://www.tacc.utexas.edu/research-development/tacc-projects/lmod' homepage = 'https://www.tacc.utexas.edu/research-development/tacc-projects/lmod' # NOQA: ignore=E501
url = 'https://github.com/TACC/Lmod/archive/6.4.1.tar.gz' url = 'https://github.com/TACC/Lmod/archive/6.4.1.tar.gz'
version('6.4.1', '7978ba777c8aa41a4d8c05fec5f780f4') version('6.4.1', '7978ba777c8aa41a4d8c05fec5f780f4')
@ -48,8 +48,10 @@ class Lmod(Package):
parallel = False parallel = False
def setup_environment(self, spack_env, run_env): def setup_environment(self, spack_env, run_env):
stage_lua_path = join_path(self.stage.path, 'Lmod-{version}', 'src', '?.lua') stage_lua_path = join_path(
spack_env.append_path('LUA_PATH', stage_lua_path.format(version=self.version), separator=';') self.stage.path, 'Lmod-{version}', 'src', '?.lua')
spack_env.append_path('LUA_PATH', stage_lua_path.format(
version=self.version), separator=';')
def install(self, spec, prefix): def install(self, spec, prefix):
configure('--prefix=%s' % prefix) configure('--prefix=%s' % prefix)

View file

@ -27,11 +27,13 @@
class LuaLuafilesystem(Package): class LuaLuafilesystem(Package):
""" """
LuaFileSystem is a Lua library developed to complement the set of functions related to file LuaFileSystem is a Lua library developed to complement the set of
systems offered by the standard Lua distribution. functions related to file systems offered by the standard Lua distribution.
LuaFileSystem offers a portable way to access the underlying directory structure and file attributes. LuaFileSystem LuaFileSystem offers a portable way to access the underlying directory
is free software and uses the same license as Lua 5.1 structure and file attributes.
LuaFileSystem is free software and uses the same license as Lua 5.1
""" """
homepage = 'http://keplerproject.github.io/luafilesystem' homepage = 'http://keplerproject.github.io/luafilesystem'
url = 'https://github.com/keplerproject/luafilesystem/archive/v_1_6_3.tar.gz' url = 'https://github.com/keplerproject/luafilesystem/archive/v_1_6_3.tar.gz'
@ -41,6 +43,9 @@ class LuaLuafilesystem(Package):
extends('lua') extends('lua')
def install(self, spec, prefix): def install(self, spec, prefix):
version = self.spec.version rockspec_fmt = join_path(self.stage.path,
rockspec_format = join_path(self.stage.path, 'luafilesystem-v_{version.underscored}', 'rockspecs', 'luafilesystem-{version.dotted}-1.rockspec') 'luafilesystem-v_{version.underscored}',
luarocks('--tree=' + prefix, 'install', rockspec_format.format(version=self.spec.version)) 'rockspecs',
'luafilesystem-{version.dotted}-1.rockspec')
luarocks('--tree=' + prefix, 'install',
rockspec_fmt.format(version=self.spec.version))

View file

@ -57,7 +57,7 @@ class Lua(Package):
placement='luarocks') placement='luarocks')
def install(self, spec, prefix): def install(self, spec, prefix):
if spec.satisfies("arch=darwin-i686") or spec.satisfies("arch=darwin-x86_64"): if spec.satisfies("arch=darwin-i686") or spec.satisfies("arch=darwin-x86_64"): # NOQA: ignore=E501
target = 'macosx' target = 'macosx'
else: else:
target = 'linux' target = 'linux'
@ -156,4 +156,5 @@ def setup_dependent_package(self, module, ext_spec):
""" """
# Lua extension builds can have lua and luarocks executable functions # Lua extension builds can have lua and luarocks executable functions
module.lua = Executable(join_path(self.spec.prefix.bin, 'lua')) module.lua = Executable(join_path(self.spec.prefix.bin, 'lua'))
module.luarocks = Executable(join_path(self.spec.prefix.bin, 'luarocks')) module.luarocks = Executable(
join_path(self.spec.prefix.bin, 'luarocks'))