Merge pull request #1026 from epfl-scitas/packages/lmod
lmod : updated package and dependencies
This commit is contained in:
commit
1b28991e0a
5 changed files with 139 additions and 151 deletions
|
@ -43,7 +43,6 @@ def assert_ver_lt(self, a, b):
|
||||||
self.assertFalse(a > b)
|
self.assertFalse(a > b)
|
||||||
self.assertFalse(a >= b)
|
self.assertFalse(a >= b)
|
||||||
|
|
||||||
|
|
||||||
def assert_ver_gt(self, a, b):
|
def assert_ver_gt(self, a, b):
|
||||||
a, b = ver(a), ver(b)
|
a, b = ver(a), ver(b)
|
||||||
self.assertTrue(a > b)
|
self.assertTrue(a > b)
|
||||||
|
@ -53,7 +52,6 @@ def assert_ver_gt(self, a, b):
|
||||||
self.assertFalse(a < b)
|
self.assertFalse(a < b)
|
||||||
self.assertFalse(a <= b)
|
self.assertFalse(a <= b)
|
||||||
|
|
||||||
|
|
||||||
def assert_ver_eq(self, a, b):
|
def assert_ver_eq(self, a, b):
|
||||||
a, b = ver(a), ver(b)
|
a, b = ver(a), ver(b)
|
||||||
self.assertFalse(a > b)
|
self.assertFalse(a > b)
|
||||||
|
@ -63,55 +61,43 @@ def assert_ver_eq(self, a, b):
|
||||||
self.assertFalse(a < b)
|
self.assertFalse(a < b)
|
||||||
self.assertTrue(a <= b)
|
self.assertTrue(a <= b)
|
||||||
|
|
||||||
|
|
||||||
def assert_in(self, needle, haystack):
|
def assert_in(self, needle, haystack):
|
||||||
self.assertTrue(ver(needle) in ver(haystack))
|
self.assertTrue(ver(needle) in ver(haystack))
|
||||||
|
|
||||||
|
|
||||||
def assert_not_in(self, needle, haystack):
|
def assert_not_in(self, needle, haystack):
|
||||||
self.assertFalse(ver(needle) in ver(haystack))
|
self.assertFalse(ver(needle) in ver(haystack))
|
||||||
|
|
||||||
|
|
||||||
def assert_canonical(self, canonical_list, version_list):
|
def assert_canonical(self, canonical_list, version_list):
|
||||||
self.assertEqual(ver(canonical_list), ver(version_list))
|
self.assertEqual(ver(canonical_list), ver(version_list))
|
||||||
|
|
||||||
|
|
||||||
def assert_overlaps(self, v1, v2):
|
def assert_overlaps(self, v1, v2):
|
||||||
self.assertTrue(ver(v1).overlaps(ver(v2)))
|
self.assertTrue(ver(v1).overlaps(ver(v2)))
|
||||||
|
|
||||||
|
|
||||||
def assert_no_overlap(self, v1, v2):
|
def assert_no_overlap(self, v1, v2):
|
||||||
self.assertFalse(ver(v1).overlaps(ver(v2)))
|
self.assertFalse(ver(v1).overlaps(ver(v2)))
|
||||||
|
|
||||||
|
|
||||||
def assert_satisfies(self, v1, v2):
|
def assert_satisfies(self, v1, v2):
|
||||||
self.assertTrue(ver(v1).satisfies(ver(v2)))
|
self.assertTrue(ver(v1).satisfies(ver(v2)))
|
||||||
|
|
||||||
|
|
||||||
def assert_does_not_satisfy(self, v1, v2):
|
def assert_does_not_satisfy(self, v1, v2):
|
||||||
self.assertFalse(ver(v1).satisfies(ver(v2)))
|
self.assertFalse(ver(v1).satisfies(ver(v2)))
|
||||||
|
|
||||||
|
|
||||||
def check_intersection(self, expected, a, b):
|
def check_intersection(self, expected, a, b):
|
||||||
self.assertEqual(ver(expected), ver(a).intersection(ver(b)))
|
self.assertEqual(ver(expected), ver(a).intersection(ver(b)))
|
||||||
|
|
||||||
|
|
||||||
def check_union(self, expected, a, b):
|
def check_union(self, expected, a, b):
|
||||||
self.assertEqual(ver(expected), ver(a).union(ver(b)))
|
self.assertEqual(ver(expected), ver(a).union(ver(b)))
|
||||||
|
|
||||||
|
|
||||||
def test_two_segments(self):
|
def test_two_segments(self):
|
||||||
self.assert_ver_eq('1.0', '1.0')
|
self.assert_ver_eq('1.0', '1.0')
|
||||||
self.assert_ver_lt('1.0', '2.0')
|
self.assert_ver_lt('1.0', '2.0')
|
||||||
self.assert_ver_gt('2.0', '1.0')
|
self.assert_ver_gt('2.0', '1.0')
|
||||||
|
|
||||||
|
|
||||||
def test_three_segments(self):
|
def test_three_segments(self):
|
||||||
self.assert_ver_eq('2.0.1', '2.0.1')
|
self.assert_ver_eq('2.0.1', '2.0.1')
|
||||||
self.assert_ver_lt('2.0', '2.0.1')
|
self.assert_ver_lt('2.0', '2.0.1')
|
||||||
self.assert_ver_gt('2.0.1', '2.0')
|
self.assert_ver_gt('2.0.1', '2.0')
|
||||||
|
|
||||||
|
|
||||||
def test_alpha(self):
|
def test_alpha(self):
|
||||||
# TODO: not sure whether I like this. 2.0.1a is *usually*
|
# TODO: not sure whether I like this. 2.0.1a is *usually*
|
||||||
# TODO: less than 2.0.1, but special-casing it makes version
|
# TODO: less than 2.0.1, but special-casing it makes version
|
||||||
|
@ -120,7 +106,6 @@ def test_alpha(self):
|
||||||
self.assert_ver_gt('2.0.1a', '2.0.1')
|
self.assert_ver_gt('2.0.1a', '2.0.1')
|
||||||
self.assert_ver_lt('2.0.1', '2.0.1a')
|
self.assert_ver_lt('2.0.1', '2.0.1a')
|
||||||
|
|
||||||
|
|
||||||
def test_patch(self):
|
def test_patch(self):
|
||||||
self.assert_ver_eq('5.5p1', '5.5p1')
|
self.assert_ver_eq('5.5p1', '5.5p1')
|
||||||
self.assert_ver_lt('5.5p1', '5.5p2')
|
self.assert_ver_lt('5.5p1', '5.5p2')
|
||||||
|
@ -129,7 +114,6 @@ def test_patch(self):
|
||||||
self.assert_ver_lt('5.5p1', '5.5p10')
|
self.assert_ver_lt('5.5p1', '5.5p10')
|
||||||
self.assert_ver_gt('5.5p10', '5.5p1')
|
self.assert_ver_gt('5.5p10', '5.5p1')
|
||||||
|
|
||||||
|
|
||||||
def test_num_alpha_with_no_separator(self):
|
def test_num_alpha_with_no_separator(self):
|
||||||
self.assert_ver_lt('10xyz', '10.1xyz')
|
self.assert_ver_lt('10xyz', '10.1xyz')
|
||||||
self.assert_ver_gt('10.1xyz', '10xyz')
|
self.assert_ver_gt('10.1xyz', '10xyz')
|
||||||
|
@ -137,7 +121,6 @@ def test_num_alpha_with_no_separator(self):
|
||||||
self.assert_ver_lt('xyz10', 'xyz10.1')
|
self.assert_ver_lt('xyz10', 'xyz10.1')
|
||||||
self.assert_ver_gt('xyz10.1', 'xyz10')
|
self.assert_ver_gt('xyz10.1', 'xyz10')
|
||||||
|
|
||||||
|
|
||||||
def test_alpha_with_dots(self):
|
def test_alpha_with_dots(self):
|
||||||
self.assert_ver_eq('xyz.4', 'xyz.4')
|
self.assert_ver_eq('xyz.4', 'xyz.4')
|
||||||
self.assert_ver_lt('xyz.4', '8')
|
self.assert_ver_lt('xyz.4', '8')
|
||||||
|
@ -145,30 +128,25 @@ def test_alpha_with_dots(self):
|
||||||
self.assert_ver_lt('xyz.4', '2')
|
self.assert_ver_lt('xyz.4', '2')
|
||||||
self.assert_ver_gt('2', 'xyz.4')
|
self.assert_ver_gt('2', 'xyz.4')
|
||||||
|
|
||||||
|
|
||||||
def test_nums_and_patch(self):
|
def test_nums_and_patch(self):
|
||||||
self.assert_ver_lt('5.5p2', '5.6p1')
|
self.assert_ver_lt('5.5p2', '5.6p1')
|
||||||
self.assert_ver_gt('5.6p1', '5.5p2')
|
self.assert_ver_gt('5.6p1', '5.5p2')
|
||||||
self.assert_ver_lt('5.6p1', '6.5p1')
|
self.assert_ver_lt('5.6p1', '6.5p1')
|
||||||
self.assert_ver_gt('6.5p1', '5.6p1')
|
self.assert_ver_gt('6.5p1', '5.6p1')
|
||||||
|
|
||||||
|
|
||||||
def test_rc_versions(self):
|
def test_rc_versions(self):
|
||||||
self.assert_ver_gt('6.0.rc1', '6.0')
|
self.assert_ver_gt('6.0.rc1', '6.0')
|
||||||
self.assert_ver_lt('6.0', '6.0.rc1')
|
self.assert_ver_lt('6.0', '6.0.rc1')
|
||||||
|
|
||||||
|
|
||||||
def test_alpha_beta(self):
|
def test_alpha_beta(self):
|
||||||
self.assert_ver_gt('10b2', '10a1')
|
self.assert_ver_gt('10b2', '10a1')
|
||||||
self.assert_ver_lt('10a2', '10b2')
|
self.assert_ver_lt('10a2', '10b2')
|
||||||
|
|
||||||
|
|
||||||
def test_double_alpha(self):
|
def test_double_alpha(self):
|
||||||
self.assert_ver_eq('1.0aa', '1.0aa')
|
self.assert_ver_eq('1.0aa', '1.0aa')
|
||||||
self.assert_ver_lt('1.0a', '1.0aa')
|
self.assert_ver_lt('1.0a', '1.0aa')
|
||||||
self.assert_ver_gt('1.0aa', '1.0a')
|
self.assert_ver_gt('1.0aa', '1.0a')
|
||||||
|
|
||||||
|
|
||||||
def test_padded_numbers(self):
|
def test_padded_numbers(self):
|
||||||
self.assert_ver_eq('10.0001', '10.0001')
|
self.assert_ver_eq('10.0001', '10.0001')
|
||||||
self.assert_ver_eq('10.0001', '10.1')
|
self.assert_ver_eq('10.0001', '10.1')
|
||||||
|
@ -176,24 +154,20 @@ def test_padded_numbers(self):
|
||||||
self.assert_ver_lt('10.0001', '10.0039')
|
self.assert_ver_lt('10.0001', '10.0039')
|
||||||
self.assert_ver_gt('10.0039', '10.0001')
|
self.assert_ver_gt('10.0039', '10.0001')
|
||||||
|
|
||||||
|
|
||||||
def test_close_numbers(self):
|
def test_close_numbers(self):
|
||||||
self.assert_ver_lt('4.999.9', '5.0')
|
self.assert_ver_lt('4.999.9', '5.0')
|
||||||
self.assert_ver_gt('5.0', '4.999.9')
|
self.assert_ver_gt('5.0', '4.999.9')
|
||||||
|
|
||||||
|
|
||||||
def test_date_stamps(self):
|
def test_date_stamps(self):
|
||||||
self.assert_ver_eq('20101121', '20101121')
|
self.assert_ver_eq('20101121', '20101121')
|
||||||
self.assert_ver_lt('20101121', '20101122')
|
self.assert_ver_lt('20101121', '20101122')
|
||||||
self.assert_ver_gt('20101122', '20101121')
|
self.assert_ver_gt('20101122', '20101121')
|
||||||
|
|
||||||
|
|
||||||
def test_underscores(self):
|
def test_underscores(self):
|
||||||
self.assert_ver_eq('2_0', '2_0')
|
self.assert_ver_eq('2_0', '2_0')
|
||||||
self.assert_ver_eq('2.0', '2_0')
|
self.assert_ver_eq('2.0', '2_0')
|
||||||
self.assert_ver_eq('2_0', '2.0')
|
self.assert_ver_eq('2_0', '2.0')
|
||||||
|
|
||||||
|
|
||||||
def test_rpm_oddities(self):
|
def test_rpm_oddities(self):
|
||||||
self.assert_ver_eq('1b.fc17', '1b.fc17')
|
self.assert_ver_eq('1b.fc17', '1b.fc17')
|
||||||
self.assert_ver_lt('1b.fc17', '1.fc17')
|
self.assert_ver_lt('1b.fc17', '1.fc17')
|
||||||
|
@ -202,7 +176,6 @@ def test_rpm_oddities(self):
|
||||||
self.assert_ver_gt('1g.fc17', '1.fc17')
|
self.assert_ver_gt('1g.fc17', '1.fc17')
|
||||||
self.assert_ver_lt('1.fc17', '1g.fc17')
|
self.assert_ver_lt('1.fc17', '1g.fc17')
|
||||||
|
|
||||||
|
|
||||||
# Stuff below here is not taken from RPM's tests and is
|
# Stuff below here is not taken from RPM's tests and is
|
||||||
# unique to spack
|
# unique to spack
|
||||||
def test_version_ranges(self):
|
def test_version_ranges(self):
|
||||||
|
@ -214,7 +187,6 @@ def test_version_ranges(self):
|
||||||
self.assert_ver_lt('1.2:1.4', '1.5:1.6')
|
self.assert_ver_lt('1.2:1.4', '1.5:1.6')
|
||||||
self.assert_ver_gt('1.5:1.6', '1.2:1.4')
|
self.assert_ver_gt('1.5:1.6', '1.2:1.4')
|
||||||
|
|
||||||
|
|
||||||
def test_contains(self):
|
def test_contains(self):
|
||||||
self.assert_in('1.3', '1.2:1.4')
|
self.assert_in('1.3', '1.2:1.4')
|
||||||
self.assert_in('1.2.5', '1.2:1.4')
|
self.assert_in('1.2.5', '1.2:1.4')
|
||||||
|
@ -233,7 +205,6 @@ def test_contains(self):
|
||||||
self.assert_in('1.4.1', '1.2.7:1.4')
|
self.assert_in('1.4.1', '1.2.7:1.4')
|
||||||
self.assert_not_in('1.4.1', '1.2.7:1.4.0')
|
self.assert_not_in('1.4.1', '1.2.7:1.4.0')
|
||||||
|
|
||||||
|
|
||||||
def test_in_list(self):
|
def test_in_list(self):
|
||||||
self.assert_in('1.2', ['1.5', '1.2', '1.3'])
|
self.assert_in('1.2', ['1.5', '1.2', '1.3'])
|
||||||
self.assert_in('1.2.5', ['1.5', '1.2:1.3'])
|
self.assert_in('1.2.5', ['1.5', '1.2:1.3'])
|
||||||
|
@ -245,7 +216,6 @@ def test_in_list(self):
|
||||||
self.assert_not_in('1.2.5:1.5', ['1.5', '1.2:1.3'])
|
self.assert_not_in('1.2.5:1.5', ['1.5', '1.2:1.3'])
|
||||||
self.assert_not_in('1.1:1.2.5', ['1.5', '1.2:1.3'])
|
self.assert_not_in('1.1:1.2.5', ['1.5', '1.2:1.3'])
|
||||||
|
|
||||||
|
|
||||||
def test_ranges_overlap(self):
|
def test_ranges_overlap(self):
|
||||||
self.assert_overlaps('1.2', '1.2')
|
self.assert_overlaps('1.2', '1.2')
|
||||||
self.assert_overlaps('1.2.1', '1.2.1')
|
self.assert_overlaps('1.2.1', '1.2.1')
|
||||||
|
@ -262,7 +232,6 @@ def test_ranges_overlap(self):
|
||||||
self.assert_overlaps(':', '1.6:1.9')
|
self.assert_overlaps(':', '1.6:1.9')
|
||||||
self.assert_overlaps('1.6:1.9', ':')
|
self.assert_overlaps('1.6:1.9', ':')
|
||||||
|
|
||||||
|
|
||||||
def test_overlap_with_containment(self):
|
def test_overlap_with_containment(self):
|
||||||
self.assert_in('1.6.5', '1.6')
|
self.assert_in('1.6.5', '1.6')
|
||||||
self.assert_in('1.6.5', ':1.6')
|
self.assert_in('1.6.5', ':1.6')
|
||||||
|
@ -273,7 +242,6 @@ def test_overlap_with_containment(self):
|
||||||
self.assert_not_in(':1.6', '1.6.5')
|
self.assert_not_in(':1.6', '1.6.5')
|
||||||
self.assert_in('1.6.5', ':1.6')
|
self.assert_in('1.6.5', ':1.6')
|
||||||
|
|
||||||
|
|
||||||
def test_lists_overlap(self):
|
def test_lists_overlap(self):
|
||||||
self.assert_overlaps('1.2b:1.7,5', '1.6:1.9,1')
|
self.assert_overlaps('1.2b:1.7,5', '1.6:1.9,1')
|
||||||
self.assert_overlaps('1,2,3,4,5', '3,4,5,6,7')
|
self.assert_overlaps('1,2,3,4,5', '3,4,5,6,7')
|
||||||
|
@ -287,7 +255,6 @@ def test_lists_overlap(self):
|
||||||
self.assert_no_overlap('1,2,3,4,5', '6,7')
|
self.assert_no_overlap('1,2,3,4,5', '6,7')
|
||||||
self.assert_no_overlap('1,2,3,4,5', '6:7')
|
self.assert_no_overlap('1,2,3,4,5', '6:7')
|
||||||
|
|
||||||
|
|
||||||
def test_canonicalize_list(self):
|
def test_canonicalize_list(self):
|
||||||
self.assert_canonical(['1.2', '1.3', '1.4'],
|
self.assert_canonical(['1.2', '1.3', '1.4'],
|
||||||
['1.2', '1.3', '1.3', '1.4'])
|
['1.2', '1.3', '1.3', '1.4'])
|
||||||
|
@ -316,7 +283,6 @@ def test_canonicalize_list(self):
|
||||||
self.assert_canonical([':'],
|
self.assert_canonical([':'],
|
||||||
[':,1.3, 1.3.1,1.3.9,1.4 : 1.5 , 1.3 : 1.4'])
|
[':,1.3, 1.3.1,1.3.9,1.4 : 1.5 , 1.3 : 1.4'])
|
||||||
|
|
||||||
|
|
||||||
def test_intersection(self):
|
def test_intersection(self):
|
||||||
self.check_intersection('2.5',
|
self.check_intersection('2.5',
|
||||||
'1.0:2.5', '2.5:3.0')
|
'1.0:2.5', '2.5:3.0')
|
||||||
|
@ -325,12 +291,11 @@ def test_intersection(self):
|
||||||
self.check_intersection('0:1', ':', '0:1')
|
self.check_intersection('0:1', ':', '0:1')
|
||||||
|
|
||||||
self.check_intersection(['1.0', '2.5:2.7'],
|
self.check_intersection(['1.0', '2.5:2.7'],
|
||||||
['1.0:2.7'], ['2.5:3.0','1.0'])
|
['1.0:2.7'], ['2.5:3.0', '1.0'])
|
||||||
self.check_intersection(['2.5:2.7'],
|
self.check_intersection(['2.5:2.7'],
|
||||||
['1.1:2.7'], ['2.5:3.0','1.0'])
|
['1.1:2.7'], ['2.5:3.0', '1.0'])
|
||||||
self.check_intersection(['0:1'], [':'], ['0:1'])
|
self.check_intersection(['0:1'], [':'], ['0:1'])
|
||||||
|
|
||||||
|
|
||||||
def test_intersect_with_containment(self):
|
def test_intersect_with_containment(self):
|
||||||
self.check_intersection('1.6.5', '1.6.5', ':1.6')
|
self.check_intersection('1.6.5', '1.6.5', ':1.6')
|
||||||
self.check_intersection('1.6.5', ':1.6', '1.6.5')
|
self.check_intersection('1.6.5', ':1.6', '1.6.5')
|
||||||
|
@ -338,7 +303,6 @@ def test_intersect_with_containment(self):
|
||||||
self.check_intersection('1.6:1.6.5', ':1.6.5', '1.6')
|
self.check_intersection('1.6:1.6.5', ':1.6.5', '1.6')
|
||||||
self.check_intersection('1.6:1.6.5', '1.6', ':1.6.5')
|
self.check_intersection('1.6:1.6.5', '1.6', ':1.6.5')
|
||||||
|
|
||||||
|
|
||||||
def test_union_with_containment(self):
|
def test_union_with_containment(self):
|
||||||
self.check_union(':1.6', '1.6.5', ':1.6')
|
self.check_union(':1.6', '1.6.5', ':1.6')
|
||||||
self.check_union(':1.6', ':1.6', '1.6.5')
|
self.check_union(':1.6', ':1.6', '1.6.5')
|
||||||
|
@ -346,8 +310,6 @@ def test_union_with_containment(self):
|
||||||
self.check_union(':1.6', ':1.6.5', '1.6')
|
self.check_union(':1.6', ':1.6.5', '1.6')
|
||||||
self.check_union(':1.6', '1.6', ':1.6.5')
|
self.check_union(':1.6', '1.6', ':1.6.5')
|
||||||
|
|
||||||
|
|
||||||
def test_union_with_containment(self):
|
|
||||||
self.check_union(':', '1.0:', ':2.0')
|
self.check_union(':', '1.0:', ':2.0')
|
||||||
|
|
||||||
self.check_union('1:4', '1:3', '2:4')
|
self.check_union('1:4', '1:3', '2:4')
|
||||||
|
@ -356,7 +318,6 @@ def test_union_with_containment(self):
|
||||||
# Tests successor/predecessor case.
|
# Tests successor/predecessor case.
|
||||||
self.check_union('1:4', '1:2', '3:4')
|
self.check_union('1:4', '1:2', '3:4')
|
||||||
|
|
||||||
|
|
||||||
def test_basic_version_satisfaction(self):
|
def test_basic_version_satisfaction(self):
|
||||||
self.assert_satisfies('4.7.3', '4.7.3')
|
self.assert_satisfies('4.7.3', '4.7.3')
|
||||||
|
|
||||||
|
@ -372,7 +333,6 @@ def test_basic_version_satisfaction(self):
|
||||||
self.assert_does_not_satisfy('4.8', '4.9')
|
self.assert_does_not_satisfy('4.8', '4.9')
|
||||||
self.assert_does_not_satisfy('4', '4.9')
|
self.assert_does_not_satisfy('4', '4.9')
|
||||||
|
|
||||||
|
|
||||||
def test_basic_version_satisfaction_in_lists(self):
|
def test_basic_version_satisfaction_in_lists(self):
|
||||||
self.assert_satisfies(['4.7.3'], ['4.7.3'])
|
self.assert_satisfies(['4.7.3'], ['4.7.3'])
|
||||||
|
|
||||||
|
@ -388,7 +348,6 @@ def test_basic_version_satisfaction_in_lists(self):
|
||||||
self.assert_does_not_satisfy(['4.8'], ['4.9'])
|
self.assert_does_not_satisfy(['4.8'], ['4.9'])
|
||||||
self.assert_does_not_satisfy(['4'], ['4.9'])
|
self.assert_does_not_satisfy(['4'], ['4.9'])
|
||||||
|
|
||||||
|
|
||||||
def test_version_range_satisfaction(self):
|
def test_version_range_satisfaction(self):
|
||||||
self.assert_satisfies('4.7b6', '4.3:4.7')
|
self.assert_satisfies('4.7b6', '4.3:4.7')
|
||||||
self.assert_satisfies('4.3.0', '4.3:4.7')
|
self.assert_satisfies('4.3.0', '4.3:4.7')
|
||||||
|
@ -400,7 +359,6 @@ def test_version_range_satisfaction(self):
|
||||||
self.assert_satisfies('4.7b6', '4.3:4.7')
|
self.assert_satisfies('4.7b6', '4.3:4.7')
|
||||||
self.assert_does_not_satisfy('4.8.0', '4.3:4.7')
|
self.assert_does_not_satisfy('4.8.0', '4.3:4.7')
|
||||||
|
|
||||||
|
|
||||||
def test_version_range_satisfaction_in_lists(self):
|
def test_version_range_satisfaction_in_lists(self):
|
||||||
self.assert_satisfies(['4.7b6'], ['4.3:4.7'])
|
self.assert_satisfies(['4.7b6'], ['4.3:4.7'])
|
||||||
self.assert_satisfies(['4.3.0'], ['4.3:4.7'])
|
self.assert_satisfies(['4.3.0'], ['4.3:4.7'])
|
||||||
|
@ -423,3 +381,11 @@ def test_satisfaction_with_lists(self):
|
||||||
|
|
||||||
self.assert_satisfies('4.8.0', '4.2, 4.3:4.8')
|
self.assert_satisfies('4.8.0', '4.2, 4.3:4.8')
|
||||||
self.assert_satisfies('4.8.2', '4.2, 4.3:4.8')
|
self.assert_satisfies('4.8.2', '4.2, 4.3:4.8')
|
||||||
|
|
||||||
|
def test_formatted_strings(self):
|
||||||
|
versions = '1.2.3', '1_2_3', '1-2-3'
|
||||||
|
for item in versions:
|
||||||
|
v = Version(item)
|
||||||
|
self.assertEqual(v.dotted, '1.2.3')
|
||||||
|
self.assertEqual(v.dashed, '1-2-3')
|
||||||
|
self.assertEqual(v.underscored, '1_2_3')
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
@ -124,6 +126,17 @@ def __init__(self, string):
|
||||||
# last element of separators is ''
|
# last element of separators is ''
|
||||||
self.separators = tuple(re.split(segment_regex, string)[1:-1])
|
self.separators = tuple(re.split(segment_regex, string)[1:-1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dotted(self):
|
||||||
|
return '.'.join(str(x) for x in self.version)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def underscored(self):
|
||||||
|
return '_'.join(str(x) for x in self.version)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dashed(self):
|
||||||
|
return '-'.join(str(x) for x in self.version)
|
||||||
|
|
||||||
def up_to(self, index):
|
def up_to(self, index):
|
||||||
"""Return a version string up to the specified component, exclusive.
|
"""Return a version string up to the specified component, exclusive.
|
||||||
|
@ -131,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
|
||||||
|
@ -147,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):
|
||||||
|
@ -181,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
|
||||||
|
@ -235,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:
|
||||||
|
@ -269,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:
|
||||||
|
@ -288,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:
|
||||||
|
@ -299,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)
|
||||||
|
@ -310,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
|
||||||
|
@ -331,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:
|
||||||
|
@ -373,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])
|
||||||
|
@ -442,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):
|
||||||
|
@ -470,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
|
||||||
|
|
||||||
|
@ -479,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:
|
||||||
|
@ -501,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:
|
||||||
|
@ -515,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.
|
||||||
|
@ -524,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]):
|
||||||
|
@ -542,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:
|
||||||
|
@ -550,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:
|
||||||
|
@ -562,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:
|
||||||
|
@ -570,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:
|
||||||
|
@ -586,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):
|
||||||
|
@ -605,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
|
||||||
|
@ -633,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).
|
||||||
|
@ -656,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.
|
||||||
|
@ -678,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)
|
||||||
|
|
||||||
|
@ -730,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(','))
|
||||||
|
@ -738,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:
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
##############################################################################
|
##############################################################################
|
||||||
from spack import *
|
from spack import *
|
||||||
import os
|
|
||||||
|
|
||||||
class Lmod(Package):
|
class Lmod(Package):
|
||||||
"""
|
"""
|
||||||
|
@ -34,17 +34,25 @@ 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 = "http://sourceforge.net/projects/lmod/files/Lmod-6.0.1.tar.bz2/download"
|
url = 'https://github.com/TACC/Lmod/archive/6.4.1.tar.gz'
|
||||||
|
|
||||||
|
version('6.4.1', '7978ba777c8aa41a4d8c05fec5f780f4')
|
||||||
|
version('6.3.7', '0fa4d5a24c41cae03776f781aa2dedc1')
|
||||||
version('6.0.1', '91abf52fe5033bd419ffe2842ebe7af9')
|
version('6.0.1', '91abf52fe5033bd419ffe2842ebe7af9')
|
||||||
|
|
||||||
depends_on("lua@5.2:")
|
depends_on('lua@5.2:')
|
||||||
|
depends_on('lua-luaposix')
|
||||||
|
depends_on('lua-luafilesystem')
|
||||||
|
|
||||||
|
parallel = False
|
||||||
|
|
||||||
|
def setup_environment(self, spack_env, run_env):
|
||||||
|
stage_lua_path = join_path(
|
||||||
|
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):
|
||||||
# Add our lua to PATH
|
|
||||||
os.environ['PATH'] = spec['lua'].prefix.bin + ';' + os.environ['PATH']
|
|
||||||
|
|
||||||
configure('--prefix=%s' % prefix)
|
configure('--prefix=%s' % prefix)
|
||||||
make()
|
make('install')
|
||||||
make("install")
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
##############################################################################
|
||||||
|
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
|
||||||
|
# Produced at the Lawrence Livermore National Laboratory.
|
||||||
|
#
|
||||||
|
# This file is part of Spack.
|
||||||
|
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
|
||||||
|
# LLNL-CODE-647188
|
||||||
|
#
|
||||||
|
# For details, see https://github.com/llnl/spack
|
||||||
|
# Please also see the LICENSE file for our notice and the LGPL.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License (as
|
||||||
|
# published by the Free Software Foundation) version 2.1, February 1999.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
|
||||||
|
# conditions of the GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
##############################################################################
|
||||||
|
from spack import *
|
||||||
|
|
||||||
|
|
||||||
|
class LuaLuafilesystem(Package):
|
||||||
|
"""
|
||||||
|
LuaFileSystem is a Lua library developed to complement the set of
|
||||||
|
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 is free software and uses the same license as Lua 5.1
|
||||||
|
"""
|
||||||
|
homepage = 'http://keplerproject.github.io/luafilesystem'
|
||||||
|
url = 'https://github.com/keplerproject/luafilesystem/archive/v_1_6_3.tar.gz'
|
||||||
|
|
||||||
|
version('1_6_3', 'd0552c7e5a082f5bb2865af63fb9dc95')
|
||||||
|
|
||||||
|
extends('lua')
|
||||||
|
|
||||||
|
def install(self, spec, prefix):
|
||||||
|
rockspec_fmt = join_path(self.stage.path,
|
||||||
|
'luafilesystem-v_{version.underscored}',
|
||||||
|
'rockspecs',
|
||||||
|
'luafilesystem-{version.dotted}-1.rockspec')
|
||||||
|
luarocks('--tree=' + prefix, 'install',
|
||||||
|
rockspec_fmt.format(version=self.spec.version))
|
|
@ -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'
|
||||||
|
@ -105,6 +105,9 @@ def setup_dependent_environment(self, spack_env, run_env, extension_spec):
|
||||||
spack_env.set('LUA_PATH', ';'.join(lua_patterns), separator=';')
|
spack_env.set('LUA_PATH', ';'.join(lua_patterns), separator=';')
|
||||||
spack_env.set('LUA_CPATH', ';'.join(lua_cpatterns), separator=';')
|
spack_env.set('LUA_CPATH', ';'.join(lua_cpatterns), separator=';')
|
||||||
|
|
||||||
|
# Add LUA to PATH for dependent packages
|
||||||
|
spack_env.prepend_path('PATH', self.prefix.bin)
|
||||||
|
|
||||||
# For run time environment set only the path for extension_spec and
|
# For run time environment set only the path for extension_spec and
|
||||||
# prepend it to LUAPATH
|
# prepend it to LUAPATH
|
||||||
if extension_spec.package.extends(self.spec):
|
if extension_spec.package.extends(self.spec):
|
||||||
|
@ -153,5 +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,
|
module.luarocks = Executable(
|
||||||
'luarocks'))
|
join_path(self.spec.prefix.bin, 'luarocks'))
|
||||||
|
|
Loading…
Reference in a new issue