diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/test/versions.py | 846 |
1 files changed, 443 insertions, 403 deletions
diff --git a/lib/spack/spack/test/versions.py b/lib/spack/spack/test/versions.py index c1d427783c..71ea3af9e9 100644 --- a/lib/spack/spack/test/versions.py +++ b/lib/spack/spack/test/versions.py @@ -22,413 +22,453 @@ # License along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## -""" -These version tests were taken from the RPM source code. +"""These version tests were taken from the RPM source code. We try to maintain compatibility with RPM's version semantics where it makes sense. """ -import unittest +import pytest from spack.version import * -class VersionsTest(unittest.TestCase): - - def assert_ver_lt(self, a, b): - a, b = ver(a), ver(b) - self.assertTrue(a < b) - self.assertTrue(a <= b) - self.assertTrue(a != b) - self.assertFalse(a == b) - self.assertFalse(a > b) - self.assertFalse(a >= b) - - def assert_ver_gt(self, a, b): - a, b = ver(a), ver(b) - self.assertTrue(a > b) - self.assertTrue(a >= b) - self.assertTrue(a != b) - self.assertFalse(a == b) - self.assertFalse(a < b) - self.assertFalse(a <= b) - - def assert_ver_eq(self, a, b): - a, b = ver(a), ver(b) - self.assertFalse(a > b) - self.assertTrue(a >= b) - self.assertFalse(a != b) - self.assertTrue(a == b) - self.assertFalse(a < b) - self.assertTrue(a <= b) - - def assert_in(self, needle, haystack): - self.assertTrue(ver(needle) in ver(haystack)) - - def assert_not_in(self, needle, haystack): - self.assertFalse(ver(needle) in ver(haystack)) - - def assert_canonical(self, canonical_list, version_list): - self.assertEqual(ver(canonical_list), ver(version_list)) - - def assert_overlaps(self, v1, v2): - self.assertTrue(ver(v1).overlaps(ver(v2))) - - def assert_no_overlap(self, v1, v2): - self.assertFalse(ver(v1).overlaps(ver(v2))) - - def assert_satisfies(self, v1, v2): - self.assertTrue(ver(v1).satisfies(ver(v2))) - - def assert_does_not_satisfy(self, v1, v2): - self.assertFalse(ver(v1).satisfies(ver(v2))) - - def check_intersection(self, expected, a, b): - self.assertEqual(ver(expected), ver(a).intersection(ver(b))) - - def check_union(self, expected, a, b): - self.assertEqual(ver(expected), ver(a).union(ver(b))) - - def test_two_segments(self): - self.assert_ver_eq('1.0', '1.0') - self.assert_ver_lt('1.0', '2.0') - self.assert_ver_gt('2.0', '1.0') - self.assert_ver_eq('develop', 'develop') - self.assert_ver_lt('1.0', 'develop') - self.assert_ver_gt('develop', '1.0') - - def test_three_segments(self): - self.assert_ver_eq('2.0.1', '2.0.1') - self.assert_ver_lt('2.0', '2.0.1') - self.assert_ver_gt('2.0.1', '2.0') - - def test_alpha(self): - # 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: comparison complicated. See version.py - self.assert_ver_eq('2.0.1a', '2.0.1a') - self.assert_ver_gt('2.0.1a', '2.0.1') - self.assert_ver_lt('2.0.1', '2.0.1a') - - def test_patch(self): - self.assert_ver_eq('5.5p1', '5.5p1') - self.assert_ver_lt('5.5p1', '5.5p2') - self.assert_ver_gt('5.5p2', '5.5p1') - self.assert_ver_eq('5.5p10', '5.5p10') - self.assert_ver_lt('5.5p1', '5.5p10') - self.assert_ver_gt('5.5p10', '5.5p1') - - def test_num_alpha_with_no_separator(self): - self.assert_ver_lt('10xyz', '10.1xyz') - self.assert_ver_gt('10.1xyz', '10xyz') - self.assert_ver_eq('xyz10', 'xyz10') - self.assert_ver_lt('xyz10', 'xyz10.1') - self.assert_ver_gt('xyz10.1', 'xyz10') - - def test_alpha_with_dots(self): - self.assert_ver_eq('xyz.4', 'xyz.4') - self.assert_ver_lt('xyz.4', '8') - self.assert_ver_gt('8', 'xyz.4') - self.assert_ver_lt('xyz.4', '2') - self.assert_ver_gt('2', 'xyz.4') - - def test_nums_and_patch(self): - self.assert_ver_lt('5.5p2', '5.6p1') - self.assert_ver_gt('5.6p1', '5.5p2') - self.assert_ver_lt('5.6p1', '6.5p1') - self.assert_ver_gt('6.5p1', '5.6p1') - - def test_rc_versions(self): - self.assert_ver_gt('6.0.rc1', '6.0') - self.assert_ver_lt('6.0', '6.0.rc1') - - def test_alpha_beta(self): - self.assert_ver_gt('10b2', '10a1') - self.assert_ver_lt('10a2', '10b2') - - def test_double_alpha(self): - self.assert_ver_eq('1.0aa', '1.0aa') - self.assert_ver_lt('1.0a', '1.0aa') - self.assert_ver_gt('1.0aa', '1.0a') - - def test_padded_numbers(self): - self.assert_ver_eq('10.0001', '10.0001') - self.assert_ver_eq('10.0001', '10.1') - self.assert_ver_eq('10.1', '10.0001') - self.assert_ver_lt('10.0001', '10.0039') - self.assert_ver_gt('10.0039', '10.0001') - - def test_close_numbers(self): - self.assert_ver_lt('4.999.9', '5.0') - self.assert_ver_gt('5.0', '4.999.9') - - def test_date_stamps(self): - self.assert_ver_eq('20101121', '20101121') - self.assert_ver_lt('20101121', '20101122') - self.assert_ver_gt('20101122', '20101121') - - 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') - - def test_rpm_oddities(self): - self.assert_ver_eq('1b.fc17', '1b.fc17') - self.assert_ver_lt('1b.fc17', '1.fc17') - self.assert_ver_gt('1.fc17', '1b.fc17') - self.assert_ver_eq('1g.fc17', '1g.fc17') - self.assert_ver_gt('1g.fc17', '1.fc17') - self.assert_ver_lt('1.fc17', '1g.fc17') - - # Stuff below here is not taken from RPM's tests and is - # unique to spack - def test_version_ranges(self): - self.assert_ver_lt('1.2:1.4', '1.6') - self.assert_ver_gt('1.6', '1.2:1.4') - self.assert_ver_eq('1.2:1.4', '1.2:1.4') - self.assertNotEqual(ver('1.2:1.4'), ver('1.2: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') - - def test_contains(self): - self.assert_in('1.3', '1.2:1.4') - self.assert_in('1.2.5', '1.2:1.4') - self.assert_in('1.3.5', '1.2:1.4') - self.assert_in('1.3.5-7', '1.2:1.4') - self.assert_not_in('1.1', '1.2:1.4') - self.assert_not_in('1.5', '1.2:1.4') - - self.assert_in('1.4.2', '1.2:1.4') - self.assert_not_in('1.4.2', '1.2:1.4.0') - - self.assert_in('1.2.8', '1.2.7:1.4') - self.assert_in('1.2.7:1.4', ':') - self.assert_not_in('1.2.5', '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') - - def test_in_list(self): - 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.5', ['1.5', '1.2:1.3']) - self.assert_not_in('1.4', ['1.5', '1.2:1.3']) - - self.assert_in('1.2.5:1.2.7', [':']) - self.assert_in('1.2.5:1.2.7', ['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']) - - def test_ranges_overlap(self): - self.assert_overlaps('1.2', '1.2') - self.assert_overlaps('1.2.1', '1.2.1') - self.assert_overlaps('1.2.1b', '1.2.1b') - - self.assert_overlaps('1.2:1.7', '1.6:1.9') - self.assert_overlaps(':1.7', '1.6:1.9') - self.assert_overlaps(':1.7', ':1.9') - self.assert_overlaps(':1.7', '1.6:') - self.assert_overlaps('1.2:', '1.6:1.9') - self.assert_overlaps('1.2:', ':1.9') - self.assert_overlaps('1.2:', '1.6:') - self.assert_overlaps(':', ':') - self.assert_overlaps(':', '1.6:1.9') - self.assert_overlaps('1.6:1.9', ':') - - def test_overlap_with_containment(self): - self.assert_in('1.6.5', '1.6') - self.assert_in('1.6.5', ':1.6') - - self.assert_overlaps('1.6.5', ':1.6') - self.assert_overlaps(':1.6', '1.6.5') - - self.assert_not_in(':1.6', '1.6.5') - self.assert_in('1.6.5', ':1.6') - - def test_lists_overlap(self): - 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', '5,6,7') - self.assert_overlaps('1,2,3,4,5', '5:7') - self.assert_overlaps('1,2,3,4,5', '3, 6:7') - self.assert_overlaps('1, 2, 4, 6.5', '3, 6:7') - self.assert_overlaps('1, 2, 4, 6.5', ':, 5, 8') - self.assert_overlaps('1, 2, 4, 6.5', ':') - self.assert_no_overlap('1, 2, 4', '3, 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): - self.assert_canonical(['1.2', '1.3', '1.4'], - ['1.2', '1.3', '1.3', '1.4']) - - self.assert_canonical(['1.2', '1.3:1.4'], - ['1.2', '1.3', '1.3:1.4']) - - self.assert_canonical(['1.2', '1.3:1.4'], - ['1.2', '1.3:1.4', '1.4']) - - self.assert_canonical(['1.3:1.4'], - ['1.3:1.4', '1.3', '1.3.1', '1.3.9', '1.4']) - - self.assert_canonical(['1.3:1.4'], - ['1.3', '1.3.1', '1.3.9', '1.4', '1.3:1.4']) - - self.assert_canonical(['1.3:1.5'], - ['1.3', '1.3.1', '1.3.9', '1.4:1.5', '1.3:1.4']) - - self.assert_canonical(['1.3:1.5'], - ['1.3, 1.3.1,1.3.9,1.4:1.5,1.3:1.4']) - - self.assert_canonical(['1.3:1.5'], - ['1.3, 1.3.1,1.3.9,1.4 : 1.5 , 1.3 : 1.4']) - - self.assert_canonical([':'], - [':,1.3, 1.3.1,1.3.9,1.4 : 1.5 , 1.3 : 1.4']) - - def test_intersection(self): - self.check_intersection('2.5', - '1.0:2.5', '2.5:3.0') - self.check_intersection('2.5:2.7', - '1.0:2.7', '2.5:3.0') - self.check_intersection('0:1', ':', '0:1') - - self.check_intersection(['1.0', '2.5:2.7'], - ['1.0:2.7'], ['2.5:3.0', '1.0']) - self.check_intersection(['2.5:2.7'], - ['1.1:2.7'], ['2.5:3.0', '1.0']) - self.check_intersection(['0:1'], [':'], ['0:1']) - - 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', '1.6.5') - - 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') - - def test_union_with_containment(self): - 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.5', '1.6') - self.check_union(':1.6', '1.6', ':1.6.5') - - self.check_union(':', '1.0:', ':2.0') - - self.check_union('1:4', '1:3', '2:4') - self.check_union('1:4', '2:4', '1:3') - - # Tests successor/predecessor case. - self.check_union('1:4', '1:2', '3:4') - - def test_basic_version_satisfaction(self): - self.assert_satisfies('4.7.3', '4.7.3') - - self.assert_satisfies('4.7.3', '4.7') - self.assert_satisfies('4.7.3b2', '4.7') - self.assert_satisfies('4.7b6', '4.7') - - self.assert_satisfies('4.7.3', '4') - self.assert_satisfies('4.7.3b2', '4') - self.assert_satisfies('4.7b6', '4') - - self.assert_does_not_satisfy('4.8.0', '4.9') - self.assert_does_not_satisfy('4.8', '4.9') - self.assert_does_not_satisfy('4', '4.9') - - 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']) - self.assert_satisfies(['4.7.3b2'], ['4.7']) - self.assert_satisfies(['4.7b6'], ['4.7']) - - self.assert_satisfies(['4.7.3'], ['4']) - self.assert_satisfies(['4.7.3b2'], ['4']) - self.assert_satisfies(['4.7b6'], ['4']) - - self.assert_does_not_satisfy(['4.8.0'], ['4.9']) - self.assert_does_not_satisfy(['4.8'], ['4.9']) - self.assert_does_not_satisfy(['4'], ['4.9']) - - def test_version_range_satisfaction(self): - self.assert_satisfies('4.7b6', '4.3:4.7') - self.assert_satisfies('4.3.0', '4.3:4.7') - self.assert_satisfies('4.3.2', '4.3:4.7') - - self.assert_does_not_satisfy('4.8.0', '4.3:4.7') - self.assert_does_not_satisfy('4.3', '4.4:4.7') - - self.assert_satisfies('4.7b6', '4.3:4.7') - self.assert_does_not_satisfy('4.8.0', '4.3:4.7') - - def test_version_range_satisfaction_in_lists(self): - self.assert_satisfies(['4.7b6'], ['4.3:4.7']) - self.assert_satisfies(['4.3.0'], ['4.3:4.7']) - self.assert_satisfies(['4.3.2'], ['4.3:4.7']) - - self.assert_does_not_satisfy(['4.8.0'], ['4.3:4.7']) - self.assert_does_not_satisfy(['4.3'], ['4.4:4.7']) - - self.assert_satisfies(['4.7b6'], ['4.3:4.7']) - self.assert_does_not_satisfy(['4.8.0'], ['4.3:4.7']) - - def test_satisfaction_with_lists(self): - self.assert_satisfies('4.7', '4.3, 4.6, 4.7') - self.assert_satisfies('4.7.3', '4.3, 4.6, 4.7') - self.assert_satisfies('4.6.5', '4.3, 4.6, 4.7') - self.assert_satisfies('4.6.5.2', '4.3, 4.6, 4.7') - - self.assert_does_not_satisfy('4', '4.3, 4.6, 4.7') - self.assert_does_not_satisfy('4.8.0', '4.2, 4.3:4.7') - - self.assert_satisfies('4.8.0', '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') - self.assertEqual(v.joined, '123') - - def test_repr_and_str(self): - - def check_repr_and_str(vrs): - a = Version(vrs) - self.assertEqual(repr(a), 'Version(\'' + vrs + '\')') - b = eval(repr(a)) - self.assertEqual(a, b) - self.assertEqual(str(a), vrs) - self.assertEqual(str(a), str(b)) - - check_repr_and_str('1.2.3') - check_repr_and_str('R2016a') - check_repr_and_str('R2016a.2-3_4') - - def test_get_item(self): - a = Version('0.1_2-3') - self.assertTrue(isinstance(a[1], int)) - # Test slicing - b = a[0:2] - self.assertTrue(isinstance(b, Version)) - self.assertEqual(b, Version('0.1')) - self.assertEqual(repr(b), 'Version(\'0.1\')') - self.assertEqual(str(b), '0.1') - b = a[0:3] - self.assertTrue(isinstance(b, Version)) - self.assertEqual(b, Version('0.1_2')) - self.assertEqual(repr(b), 'Version(\'0.1_2\')') - self.assertEqual(str(b), '0.1_2') - b = a[1:] - self.assertTrue(isinstance(b, Version)) - self.assertEqual(b, Version('1_2-3')) - self.assertEqual(repr(b), 'Version(\'1_2-3\')') - self.assertEqual(str(b), '1_2-3') - # Raise TypeError on tuples - self.assertRaises(TypeError, b.__getitem__, 1, 2) - -if __name__ == '__main__': - unittest.main() +def assert_ver_lt(a, b): + """Asserts the results of comparisons when 'a' is less than 'b'.""" + a, b = ver(a), ver(b) + assert a < b + assert a <= b + assert a != b + assert not a == b + assert not a > b + assert not a >= b + + +def assert_ver_gt(a, b): + """Asserts the results of comparisons when 'a' is greater than 'b'.""" + a, b = ver(a), ver(b) + assert a > b + assert a >= b + assert a != b + assert not a == b + assert not a < b + assert not a <= b + + +def assert_ver_eq(a, b): + """Asserts the results of comparisons when 'a' is equal to 'b'.""" + a, b = ver(a), ver(b) + assert not a > b + assert a >= b + assert not a != b + assert a == b + assert not a < b + assert a <= b + + +def assert_in(needle, haystack): + """Asserts that 'needle' is in 'haystack'.""" + assert ver(needle) in ver(haystack) + + +def assert_not_in(needle, haystack): + """Asserts that 'needle' is not in 'haystack'.""" + assert ver(needle) not in ver(haystack) + + +def assert_canonical(canonical_list, version_list): + """Asserts that a redundant list is reduced to canonical form.""" + assert ver(canonical_list) == ver(version_list) + + +def assert_overlaps(v1, v2): + """Asserts that two version ranges overlaps.""" + assert ver(v1).overlaps(ver(v2)) + + +def assert_no_overlap(v1, v2): + """Asserts that two version ranges do not overlap.""" + assert not ver(v1).overlaps(ver(v2)) + + +def assert_satisfies(v1, v2): + """Asserts that 'v1' satisfies 'v2'.""" + assert ver(v1).satisfies(ver(v2)) + + +def assert_does_not_satisfy(v1, v2): + """Asserts that 'v1' does not satisfy 'v2'.""" + assert not ver(v1).satisfies(ver(v2)) + + +def check_intersection(expected, a, b): + """Asserts that 'a' intersect 'b' == 'expected'.""" + assert ver(expected) == ver(a).intersection(ver(b)) + + +def check_union(expected, a, b): + """Asserts that 'a' union 'b' == 'expected'.""" + assert ver(expected) == ver(a).union(ver(b)) + + +def test_two_segments(): + assert_ver_eq('1.0', '1.0') + assert_ver_lt('1.0', '2.0') + assert_ver_gt('2.0', '1.0') + assert_ver_eq('develop', 'develop') + assert_ver_lt('1.0', 'develop') + assert_ver_gt('develop', '1.0') + + +def test_three_segments(): + assert_ver_eq('2.0.1', '2.0.1') + assert_ver_lt('2.0', '2.0.1') + assert_ver_gt('2.0.1', '2.0') + + +def test_alpha(): + # 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: comparison complicated. See version.py + assert_ver_eq('2.0.1a', '2.0.1a') + assert_ver_gt('2.0.1a', '2.0.1') + assert_ver_lt('2.0.1', '2.0.1a') + + +def test_patch(): + assert_ver_eq('5.5p1', '5.5p1') + assert_ver_lt('5.5p1', '5.5p2') + assert_ver_gt('5.5p2', '5.5p1') + assert_ver_eq('5.5p10', '5.5p10') + assert_ver_lt('5.5p1', '5.5p10') + assert_ver_gt('5.5p10', '5.5p1') + + +def test_num_alpha_with_no_separator(): + assert_ver_lt('10xyz', '10.1xyz') + assert_ver_gt('10.1xyz', '10xyz') + assert_ver_eq('xyz10', 'xyz10') + assert_ver_lt('xyz10', 'xyz10.1') + assert_ver_gt('xyz10.1', 'xyz10') + + +def test_alpha_with_dots(): + assert_ver_eq('xyz.4', 'xyz.4') + assert_ver_lt('xyz.4', '8') + assert_ver_gt('8', 'xyz.4') + assert_ver_lt('xyz.4', '2') + assert_ver_gt('2', 'xyz.4') + + +def test_nums_and_patch(): + assert_ver_lt('5.5p2', '5.6p1') + assert_ver_gt('5.6p1', '5.5p2') + assert_ver_lt('5.6p1', '6.5p1') + assert_ver_gt('6.5p1', '5.6p1') + + +def test_rc_versions(): + assert_ver_gt('6.0.rc1', '6.0') + assert_ver_lt('6.0', '6.0.rc1') + + +def test_alpha_beta(): + assert_ver_gt('10b2', '10a1') + assert_ver_lt('10a2', '10b2') + + +def test_double_alpha(): + assert_ver_eq('1.0aa', '1.0aa') + assert_ver_lt('1.0a', '1.0aa') + assert_ver_gt('1.0aa', '1.0a') + + +def test_padded_numbers(): + assert_ver_eq('10.0001', '10.0001') + assert_ver_eq('10.0001', '10.1') + assert_ver_eq('10.1', '10.0001') + assert_ver_lt('10.0001', '10.0039') + assert_ver_gt('10.0039', '10.0001') + + +def test_close_numbers(): + assert_ver_lt('4.999.9', '5.0') + assert_ver_gt('5.0', '4.999.9') + + +def test_date_stamps(): + assert_ver_eq('20101121', '20101121') + assert_ver_lt('20101121', '20101122') + assert_ver_gt('20101122', '20101121') + + +def test_underscores(): + assert_ver_eq('2_0', '2_0') + assert_ver_eq('2.0', '2_0') + assert_ver_eq('2_0', '2.0') + + +def test_rpm_oddities(): + assert_ver_eq('1b.fc17', '1b.fc17') + assert_ver_lt('1b.fc17', '1.fc17') + assert_ver_gt('1.fc17', '1b.fc17') + assert_ver_eq('1g.fc17', '1g.fc17') + assert_ver_gt('1g.fc17', '1.fc17') + assert_ver_lt('1.fc17', '1g.fc17') + + +# Stuff below here is not taken from RPM's tests and is +# unique to spack +def test_version_ranges(): + assert_ver_lt('1.2:1.4', '1.6') + assert_ver_gt('1.6', '1.2:1.4') + assert_ver_eq('1.2:1.4', '1.2:1.4') + assert ver('1.2:1.4') != ver('1.2:1.6') + + assert_ver_lt('1.2:1.4', '1.5:1.6') + assert_ver_gt('1.5:1.6', '1.2:1.4') + + +def test_contains(): + assert_in('1.3', '1.2:1.4') + assert_in('1.2.5', '1.2:1.4') + assert_in('1.3.5', '1.2:1.4') + assert_in('1.3.5-7', '1.2:1.4') + assert_not_in('1.1', '1.2:1.4') + assert_not_in('1.5', '1.2:1.4') + + assert_in('1.4.2', '1.2:1.4') + assert_not_in('1.4.2', '1.2:1.4.0') + + assert_in('1.2.8', '1.2.7:1.4') + assert_in('1.2.7:1.4', ':') + assert_not_in('1.2.5', '1.2.7:1.4') + + assert_in('1.4.1', '1.2.7:1.4') + assert_not_in('1.4.1', '1.2.7:1.4.0') + + +def test_in_list(): + assert_in('1.2', ['1.5', '1.2', '1.3']) + assert_in('1.2.5', ['1.5', '1.2:1.3']) + assert_in('1.5', ['1.5', '1.2:1.3']) + assert_not_in('1.4', ['1.5', '1.2:1.3']) + + assert_in('1.2.5:1.2.7', [':']) + assert_in('1.2.5:1.2.7', ['1.5', '1.2:1.3']) + assert_not_in('1.2.5:1.5', ['1.5', '1.2:1.3']) + assert_not_in('1.1:1.2.5', ['1.5', '1.2:1.3']) + + +def test_ranges_overlap(): + assert_overlaps('1.2', '1.2') + assert_overlaps('1.2.1', '1.2.1') + assert_overlaps('1.2.1b', '1.2.1b') + + assert_overlaps('1.2:1.7', '1.6:1.9') + assert_overlaps(':1.7', '1.6:1.9') + assert_overlaps(':1.7', ':1.9') + assert_overlaps(':1.7', '1.6:') + assert_overlaps('1.2:', '1.6:1.9') + assert_overlaps('1.2:', ':1.9') + assert_overlaps('1.2:', '1.6:') + assert_overlaps(':', ':') + assert_overlaps(':', '1.6:1.9') + assert_overlaps('1.6:1.9', ':') + + +def test_overlap_with_containment(): + assert_in('1.6.5', '1.6') + assert_in('1.6.5', ':1.6') + + assert_overlaps('1.6.5', ':1.6') + assert_overlaps(':1.6', '1.6.5') + + assert_not_in(':1.6', '1.6.5') + assert_in('1.6.5', ':1.6') + + +def test_lists_overlap(): + assert_overlaps('1.2b:1.7,5', '1.6:1.9,1') + assert_overlaps('1,2,3,4,5', '3,4,5,6,7') + assert_overlaps('1,2,3,4,5', '5,6,7') + assert_overlaps('1,2,3,4,5', '5:7') + assert_overlaps('1,2,3,4,5', '3, 6:7') + assert_overlaps('1, 2, 4, 6.5', '3, 6:7') + assert_overlaps('1, 2, 4, 6.5', ':, 5, 8') + assert_overlaps('1, 2, 4, 6.5', ':') + assert_no_overlap('1, 2, 4', '3, 6:7') + assert_no_overlap('1,2,3,4,5', '6,7') + assert_no_overlap('1,2,3,4,5', '6:7') + + +def test_canonicalize_list(): + assert_canonical(['1.2', '1.3', '1.4'], ['1.2', '1.3', '1.3', '1.4']) + + assert_canonical(['1.2', '1.3:1.4'], ['1.2', '1.3', '1.3:1.4']) + + assert_canonical(['1.2', '1.3:1.4'], ['1.2', '1.3:1.4', '1.4']) + + assert_canonical(['1.3:1.4'], ['1.3:1.4', '1.3', '1.3.1', '1.3.9', '1.4']) + + assert_canonical(['1.3:1.4'], ['1.3', '1.3.1', '1.3.9', '1.4', '1.3:1.4']) + + assert_canonical( + ['1.3:1.5'], ['1.3', '1.3.1', '1.3.9', '1.4:1.5', '1.3:1.4'] + ) + + assert_canonical(['1.3:1.5'], ['1.3, 1.3.1,1.3.9,1.4:1.5,1.3:1.4']) + + assert_canonical(['1.3:1.5'], ['1.3, 1.3.1,1.3.9,1.4 : 1.5 , 1.3 : 1.4']) + + assert_canonical([':'], [':,1.3, 1.3.1,1.3.9,1.4 : 1.5 , 1.3 : 1.4']) + + +def test_intersection(): + check_intersection('2.5', '1.0:2.5', '2.5:3.0') + check_intersection('2.5:2.7', '1.0:2.7', '2.5:3.0') + check_intersection('0:1', ':', '0:1') + + check_intersection(['1.0', '2.5:2.7'], ['1.0:2.7'], ['2.5:3.0', '1.0']) + check_intersection(['2.5:2.7'], ['1.1:2.7'], ['2.5:3.0', '1.0']) + check_intersection(['0:1'], [':'], ['0:1']) + + +def test_intersect_with_containment(): + check_intersection('1.6.5', '1.6.5', ':1.6') + check_intersection('1.6.5', ':1.6', '1.6.5') + + check_intersection('1.6:1.6.5', ':1.6.5', '1.6') + check_intersection('1.6:1.6.5', '1.6', ':1.6.5') + + +def test_union_with_containment(): + check_union(':1.6', '1.6.5', ':1.6') + check_union(':1.6', ':1.6', '1.6.5') + + check_union(':1.6', ':1.6.5', '1.6') + check_union(':1.6', '1.6', ':1.6.5') + + check_union(':', '1.0:', ':2.0') + + check_union('1:4', '1:3', '2:4') + check_union('1:4', '2:4', '1:3') + + # Tests successor/predecessor case. + check_union('1:4', '1:2', '3:4') + + +def test_basic_version_satisfaction(): + assert_satisfies('4.7.3', '4.7.3') + + assert_satisfies('4.7.3', '4.7') + assert_satisfies('4.7.3b2', '4.7') + assert_satisfies('4.7b6', '4.7') + + assert_satisfies('4.7.3', '4') + assert_satisfies('4.7.3b2', '4') + assert_satisfies('4.7b6', '4') + + assert_does_not_satisfy('4.8.0', '4.9') + assert_does_not_satisfy('4.8', '4.9') + assert_does_not_satisfy('4', '4.9') + + +def test_basic_version_satisfaction_in_lists(): + assert_satisfies(['4.7.3'], ['4.7.3']) + + assert_satisfies(['4.7.3'], ['4.7']) + assert_satisfies(['4.7.3b2'], ['4.7']) + assert_satisfies(['4.7b6'], ['4.7']) + + assert_satisfies(['4.7.3'], ['4']) + assert_satisfies(['4.7.3b2'], ['4']) + assert_satisfies(['4.7b6'], ['4']) + + assert_does_not_satisfy(['4.8.0'], ['4.9']) + assert_does_not_satisfy(['4.8'], ['4.9']) + assert_does_not_satisfy(['4'], ['4.9']) + + +def test_version_range_satisfaction(): + assert_satisfies('4.7b6', '4.3:4.7') + assert_satisfies('4.3.0', '4.3:4.7') + assert_satisfies('4.3.2', '4.3:4.7') + + assert_does_not_satisfy('4.8.0', '4.3:4.7') + assert_does_not_satisfy('4.3', '4.4:4.7') + + assert_satisfies('4.7b6', '4.3:4.7') + assert_does_not_satisfy('4.8.0', '4.3:4.7') + + +def test_version_range_satisfaction_in_lists(): + assert_satisfies(['4.7b6'], ['4.3:4.7']) + assert_satisfies(['4.3.0'], ['4.3:4.7']) + assert_satisfies(['4.3.2'], ['4.3:4.7']) + + assert_does_not_satisfy(['4.8.0'], ['4.3:4.7']) + assert_does_not_satisfy(['4.3'], ['4.4:4.7']) + + assert_satisfies(['4.7b6'], ['4.3:4.7']) + assert_does_not_satisfy(['4.8.0'], ['4.3:4.7']) + + +def test_satisfaction_with_lists(): + assert_satisfies('4.7', '4.3, 4.6, 4.7') + assert_satisfies('4.7.3', '4.3, 4.6, 4.7') + assert_satisfies('4.6.5', '4.3, 4.6, 4.7') + assert_satisfies('4.6.5.2', '4.3, 4.6, 4.7') + + assert_does_not_satisfy('4', '4.3, 4.6, 4.7') + assert_does_not_satisfy('4.8.0', '4.2, 4.3:4.7') + + assert_satisfies('4.8.0', '4.2, 4.3:4.8') + assert_satisfies('4.8.2', '4.2, 4.3:4.8') + + +def test_formatted_strings(): + versions = '1.2.3', '1_2_3', '1-2-3' + for item in versions: + v = Version(item) + assert v.dotted == '1.2.3' + assert v.dashed == '1-2-3' + assert v.underscored == '1_2_3' + assert v.joined == '123' + + +def test_repr_and_str(): + + def check_repr_and_str(vrs): + a = Version(vrs) + assert repr(a) == 'Version(\'' + vrs + '\')' + b = eval(repr(a)) + assert a == b + assert str(a) == vrs + assert str(a) == str(b) + + check_repr_and_str('1.2.3') + check_repr_and_str('R2016a') + check_repr_and_str('R2016a.2-3_4') + + +def test_get_item(): + a = Version('0.1_2-3') + assert isinstance(a[1], int) + # Test slicing + b = a[0:2] + assert isinstance(b, Version) + assert b == Version('0.1') + assert repr(b) == 'Version(\'0.1\')' + assert str(b) == '0.1' + b = a[0:3] + assert isinstance(b, Version) + assert b == Version('0.1_2') + assert repr(b) == 'Version(\'0.1_2\')' + assert str(b) == '0.1_2' + b = a[1:] + assert isinstance(b, Version) + assert b == Version('1_2-3') + assert repr(b) == 'Version(\'1_2-3\')' + assert str(b) == '1_2-3' + # Raise TypeError on tuples + with pytest.raises(TypeError): + b.__getitem__(1, 2) |