def test_containment(self): # basic containment self.assertTrue(Version("3") in VersionRange("3+")) self.assertTrue(Version("5") in VersionRange("3..5")) self.assertTrue(Version("5_") not in VersionRange("3..5")) self.assertTrue(Version("3.0.0") in VersionRange("3+")) self.assertTrue(Version("3.0.0") not in VersionRange("3.1+")) self.assertTrue(Version("3") in VersionRange("<1|5|6|8|7|3|60+")) self.assertTrue(Version("3") in VersionRange("<1|5|6|8|7|==3|60+")) self.assertTrue(VersionRange("2.1+<4") in VersionRange("<4")) self.assertTrue(VersionRange("2.1..4") not in VersionRange("<4")) self.assertTrue(VersionRange("3") in VersionRange("3")) self.assertTrue(VersionRange("==3") in VersionRange("3")) self.assertTrue(VersionRange("3.5+<3_") in VersionRange("3")) self.assertTrue(VersionRange("3") not in VersionRange("4+<6")) self.assertTrue(VersionRange("3+<10") not in VersionRange("4+<6")) # iterating over sorted version list numbers = [2, 3, 5, 10, 11, 13, 14] versions = [Version(str(x)) for x in numbers] rev_versions = list(reversed(versions)) composite_range = VersionRange.from_versions(versions) entries = [(VersionRange(""), 7), (VersionRange("0+"), 7), (VersionRange("5+"), 5), (VersionRange("6+"), 4), (VersionRange("50+"), 0), (VersionRange(">5"), 4), (VersionRange("5"), 1), (VersionRange("6"), 0), (VersionRange("<5"), 2), (VersionRange("<6"), 3), (VersionRange("<50"), 7), (VersionRange("<=5"), 3), (VersionRange("<1"), 0), (VersionRange("2|9+"), 5), (VersionRange("3+<6|12+<13.5"), 3), (VersionRange("<1|20+"), 0), (VersionRange(">0<20"), 7)] for range_, count in entries: # brute-force containment tests matches = set(x for x in versions if x in range_) self.assertEqual(len(matches), count) # more optimal containment tests def _test_it(it): matches_ = set(version for contains, version in it if contains) self.assertEqual(matches_, matches) _test_it(range_.iter_intersect_test(versions)) _test_it(range_.iter_intersect_test(rev_versions, descending=True)) # throw in an intersection test self.assertEqual(composite_range.intersects(range_), (count != 0)) int_range = composite_range & range_ versions_ = [] if int_range is None else int_range.to_versions() self.assertEqual(set(versions_), matches) # throw in a superset test as well self.assertEqual(range_.issuperset(composite_range), (count == 7)) if count: self.assertTrue(composite_range.issuperset(int_range))
def test_containment(self): # basic containment self.assertTrue(Version("3") in VersionRange("3+")) self.assertTrue(Version("5") in VersionRange("3..5")) self.assertTrue(Version("5_") not in VersionRange("3..5")) self.assertTrue(Version("3.0.0") in VersionRange("3+")) self.assertTrue(Version("3.0.0") not in VersionRange("3.1+")) self.assertTrue(Version("3") in VersionRange("<1|5|6|8|7|3|60+")) self.assertTrue(Version("3") in VersionRange("<1|5|6|8|7|==3|60+")) self.assertTrue(VersionRange("2.1+<4") in VersionRange("<4")) self.assertTrue(VersionRange("2.1..4") not in VersionRange("<4")) self.assertTrue(VersionRange("3") in VersionRange("3")) self.assertTrue(VersionRange("==3") in VersionRange("3")) self.assertTrue(VersionRange("3.5+<3_") in VersionRange("3")) self.assertTrue(VersionRange("3") not in VersionRange("4+<6")) self.assertTrue(VersionRange("3+<10") not in VersionRange("4+<6")) # iterating over sorted version list numbers = [2, 3, 5, 10, 11, 13, 14] versions = [Version(str(x)) for x in numbers] rev_versions = list(reversed(versions)) composite_range = VersionRange.from_versions(versions) entries = [(VersionRange(""), 7), (VersionRange("0+"), 7), (VersionRange("5+"), 5), (VersionRange("6+"), 4), (VersionRange("50+"), 0), (VersionRange(">5"), 4), (VersionRange("5"), 1), (VersionRange("6"), 0), (VersionRange("<5"), 2), (VersionRange("<6"), 3), (VersionRange("<50"), 7), (VersionRange("<=5"), 3), (VersionRange("<1"), 0), (VersionRange("2|9+"), 5), (VersionRange("3+<6|12+<13.5"), 3), (VersionRange("<1|20+"), 0), (VersionRange(">0<20"), 7)] for range_, count in entries: # brute-force containment tests matches = set(x for x in versions if x in range_) self.assertEqual(len(matches), count) # more optimal containment tests def _test_it(it): matches_ = set(version for contains, version in it if contains) self.assertEqual(matches_, matches) _test_it(range_.iter_intersect_test(versions)) _test_it(range_.iter_intersect_test(rev_versions, descending=True)) # throw in an intersection test self.assertEqual(composite_range.intersects(range_), (count != 0)) int_range = composite_range & range_ versions_ = [] if int_range is None else int_range.to_versions() self.assertEqual(set(versions_), matches) # throw in a superset test as well self.assertEqual(range_.issuperset(composite_range), (count == 7)) if count: self.assertTrue(composite_range.issuperset(int_range))
def test_version_range(self): def _eq(a, b): _print("'%s' == '%s'" % (a, b)) a_range = VersionRange(a) b_range = VersionRange(b) self.assertTrue(a_range == b_range) self.assertTrue(a_range.issuperset(a_range)) self.assertTrue(a_range.issuperset(b_range)) self.assertTrue(VersionRange(str(a_range)) == a_range) self.assertTrue(VersionRange(str(b_range)) == a_range) self.assertTrue(hash(a_range) == hash(b_range)) a_ = a.replace('.', '-') a_ = a_.replace("--", "..") a_range_ = VersionRange(a_) self.assertTrue(a_range_ == a_range) self.assertTrue(hash(a_range_) == hash(a_range)) range_strs = a.split('|') ranges = [VersionRange(x) for x in range_strs] ranges_ = ranges[0].union(ranges[1:]) self.assertTrue(ranges_ == a_range) self.assertTrue(a_range | b_range == a_range) self.assertTrue(a_range - b_range is None) self.assertTrue(b_range - a_range is None) self.assertTrue(VersionRange() & a_range == a_range) self.assertTrue(b_range.span() & a_range == a_range) a_inv = a_range.inverse() self.assertTrue(a_inv == ~b_range) if a_inv: self.assertTrue(~a_inv == a_range) self.assertTrue(a_range | a_inv == VersionRange()) self.assertTrue(a_range & a_inv is None) a_ranges = a_range.split() a_range_ = a_ranges[0].union(a_ranges[1:]) self.assertTrue(a_range_ == b_range) def _and(a, b, c): _print("'%s' & '%s' == '%s'" % (a, b, c)) a_range = VersionRange(a) b_range = VersionRange(b) c_range = None if c is None else VersionRange(c) self.assertTrue(a_range & b_range == c_range) self.assertTrue(b_range & a_range == c_range) a_or_b = a_range | b_range a_and_b = a_range & b_range a_sub_b = a_range - b_range b_sub_a = b_range - a_range ranges = [a_and_b, a_sub_b, b_sub_a] ranges = [x for x in ranges if x] self.assertTrue(ranges[0].union(ranges[1:]) == a_or_b) def _inv(a, b): a_range = VersionRange(a) b_range = VersionRange(b) self.assertTrue(~a_range == b_range) self.assertTrue(~b_range == a_range) self.assertTrue(a_range | b_range == VersionRange()) self.assertTrue(a_range & b_range is None) # simple cases _print() _eq("", "") _eq("1", "1") _eq("1.0.0", "1.0.0") _eq("3+<3_", "3") _eq("_+<__", "_") _eq("1.2+<=2.0", "1.2..2.0") _eq("10+,<20", "10+<20") _eq("1+<1.0", "1+<1.0") _eq(">=2", "2+") # optimised cases _eq("3|3", "3") _eq("3|1", "1|3") _eq("5|3|1", "1|3|5") _eq("1|1_", "1+<1__") _eq("1|1_|1__", "1+,<1___") _eq("|", "") _eq("||", "||||||||") _eq("1|1_+", "1+") _eq("<1|1", "<1_") _eq("1+<3|3+<5", "1+<5") _eq(">4<6|1+<3", "1+<3|>4,<6") _eq("4+<6|1+<3|", "") _eq("4|2+", "2+") _eq("3|<5", "<5") _eq("<3|>3", ">3|<3") _eq("3+|<3", "") _eq("3+|<4", "") _eq("2+<=6|3+<5", "2..6") _eq("3+,<5|2+<=6", "2+<=6") _eq("2|2+", "2+") _eq("2|2.1+", "2+") _eq("2|<2.1", "<2_") _eq("3..3", "==3") _eq(">=3,<=3", "==3") # AND'ing _and("3", "3", "3") _and("1", "==1", "==1") _and("", "==1", "==1") _and("3", "4", None) _and("<3", "5+", None) _and("4+<6", "6+<8", None) _and("2+", "<=4", "2..4") _and("1", "1.0", "1.0") _and("4..6", "6+<8", "==6") # inverse _inv("3+", "<3") _inv("<=3", ">3") _inv("3.5", "<3.5|3.5_+") self.assertTrue(~VersionRange() is None) # odd (but valid) cases _eq(">", ">") # greater than the empty version _eq("+", "") # greater or equal to empty version (is all vers) _eq(">=", "") # equivalent to above _eq("<=", "==") # less or equal to empty version (is only empty) _eq("..", "==") # from empty version to empty version _eq("+<=", "==") # equivalent to above invalid_range = [ "4+<2", # lower bound greater than upper ">3<3", # both greater and less than same version ">3<=3", # greater and less or equal to same version "3+<3" # greater and equal to, and less than, same version ] for s in invalid_range: self.assertRaises(VersionError, VersionRange, s) invalid_syntax = [ "<", # less than the empty version "><", # both greater and less than empty version ">3>4", # both are lower bounds "<3<4", # both are upper bounds "<4>3", # upper bound before lower ",<4", # leading comma "4+,", # trailing comma "1>=", # pre-lower-op in post "+1", # post-lower-op in pre "4<", # pre-upper-op in post "1+<2<3" # more than two bounds ] for s in invalid_syntax: self.assertRaises(VersionError, VersionRange, s) # test simple logic self.assertTrue(VersionRange("").is_any()) self.assertTrue(VersionRange("2+<4").bounded()) self.assertTrue(VersionRange("2+").lower_bounded()) self.assertTrue(not VersionRange("2+").upper_bounded()) self.assertTrue(not VersionRange("2+").bounded()) self.assertTrue(VersionRange("<2").upper_bounded()) self.assertTrue(not VersionRange("<2").lower_bounded()) self.assertTrue(not VersionRange("<2").bounded()) # test range from version(s) v = Version("3") self.assertTrue( VersionRange.from_version(v, "eq") == VersionRange("==3")) self.assertTrue( VersionRange.from_version(v, "gt") == VersionRange(">3")) self.assertTrue( VersionRange.from_version(v, "gte") == VersionRange("3+")) self.assertTrue( VersionRange.from_version(v, "lt") == VersionRange("<3")) self.assertTrue( VersionRange.from_version(v, "lte") == VersionRange("<=3")) range1 = VersionRange.from_version(Version("2"), "gte") range2 = VersionRange.from_version(Version("4"), "lte") _eq(str(range1 & range2), "2..4") v2 = Version("6.0") v3 = Version("4") self.assertTrue( VersionRange.from_versions([v, v2, v3]) == VersionRange( "==3|==4|==6.0")) # test behaviour in sets def _eq2(a, b): _print("'%s' == '%s'" % (a, b)) self.assertTrue(a == b) a = VersionRange("1+<=2.5") b = VersionRange("1..2.5") c = VersionRange(">=5") d = VersionRange(">6.1.0") e = VersionRange("3.2") _eq2(set([a]) - set([a]), set()) _eq2(set([a]) - set([b]), set()) _eq2(set([a, a]) - set([a]), set()) _eq2(set([b, c, d, e]) - set([a]), set([c, d, e])) _eq2(set([b, c, e]) | set([c, d]), set([b, c, d, e])) _eq2(set([b, c]) & set([c, d]), set([c]))
def test_version_range(self): def _eq(a, b): _print("'%s' == '%s'" % (a, b)) a_range = VersionRange(a) b_range = VersionRange(b) self.assertTrue(a_range == b_range) self.assertTrue(a_range.issuperset(a_range)) self.assertTrue(a_range.issuperset(b_range)) self.assertTrue(VersionRange(str(a_range)) == a_range) self.assertTrue(VersionRange(str(b_range)) == a_range) self.assertTrue(hash(a_range) == hash(b_range)) a_ = a.replace('.', '-') a_ = a_.replace("--", "..") a_range_ = VersionRange(a_) self.assertTrue(a_range_ == a_range) self.assertTrue(hash(a_range_) == hash(a_range)) range_strs = a.split('|') ranges = [VersionRange(x) for x in range_strs] ranges_ = ranges[0].union(ranges[1:]) self.assertTrue(ranges_ == a_range) self.assertTrue(a_range | b_range == a_range) self.assertTrue(a_range - b_range is None) self.assertTrue(b_range - a_range is None) self.assertTrue(VersionRange() & a_range == a_range) self.assertTrue(b_range.span() & a_range == a_range) a_inv = a_range.inverse() self.assertTrue(a_inv == ~b_range) if a_inv: self.assertTrue(~a_inv == a_range) self.assertTrue(a_range | a_inv == VersionRange()) self.assertTrue(a_range & a_inv is None) a_ranges = a_range.split() a_range_ = a_ranges[0].union(a_ranges[1:]) self.assertTrue(a_range_ == b_range) def _and(a, b, c): _print("'%s' & '%s' == '%s'" % (a, b, c)) a_range = VersionRange(a) b_range = VersionRange(b) c_range = None if c is None else VersionRange(c) self.assertTrue(a_range & b_range == c_range) self.assertTrue(b_range & a_range == c_range) a_or_b = a_range | b_range a_and_b = a_range & b_range a_sub_b = a_range - b_range b_sub_a = b_range - a_range ranges = [a_and_b, a_sub_b, b_sub_a] ranges = [x for x in ranges if x] self.assertTrue(ranges[0].union(ranges[1:]) == a_or_b) def _inv(a, b): a_range = VersionRange(a) b_range = VersionRange(b) self.assertTrue(~a_range == b_range) self.assertTrue(~b_range == a_range) self.assertTrue(a_range | b_range == VersionRange()) self.assertTrue(a_range & b_range is None) # simple cases _print() _eq("", "") _eq("1", "1") _eq("1.0.0", "1.0.0") _eq("3+<3_", "3") _eq("_+<__", "_") _eq("1.2+<=2.0", "1.2..2.0") _eq("10+,<20", "10+<20") _eq("1+<1.0", "1+<1.0") _eq(">=2", "2+") # optimised cases _eq("3|3", "3") _eq("3|1", "1|3") _eq("5|3|1", "1|3|5") _eq("1|1_", "1+<1__") _eq("1|1_|1__", "1+,<1___") _eq("|", "") _eq("||", "||||||||") _eq("1|1_+", "1+") _eq("<1|1", "<1_") _eq("1+<3|3+<5", "1+<5") _eq(">4<6|1+<3", "1+<3|>4,<6") _eq("4+<6|1+<3|", "") _eq("4|2+", "2+") _eq("3|<5", "<5") _eq("<3|>3", ">3|<3") _eq("3+|<3", "") _eq("3+|<4", "") _eq("2+<=6|3+<5", "2..6") _eq("3+,<5|2+<=6", "2+<=6") _eq("2|2+", "2+") _eq("2|2.1+", "2+") _eq("2|<2.1", "<2_") _eq("3..3", "==3") _eq(">=3,<=3", "==3") # AND'ing _and("3", "3", "3") _and("1", "==1", "==1") _and("", "==1", "==1") _and("3", "4", None) _and("<3", "5+", None) _and("4+<6", "6+<8", None) _and("2+", "<=4", "2..4") _and("1", "1.0", "1.0") _and("4..6", "6+<8", "==6") # inverse _inv("3+", "<3") _inv("<=3", ">3") _inv("3.5", "<3.5|3.5_+") self.assertTrue(~VersionRange() is None) # odd (but valid) cases _eq(">", ">") # greater than the empty version _eq("+", "") # greater or equal to empty version (is all vers) _eq(">=", "") # equivalent to above _eq("<=", "==") # less or equal to empty version (is only empty) _eq("..", "==") # from empty version to empty version _eq("+<=", "==") # equivalent to above invalid_range = [ "4+<2", # lower bound greater than upper ">3<3", # both greater and less than same version ">3<=3", # greater and less or equal to same version "3+<3" # greater and equal to, and less than, same version ] for s in invalid_range: self.assertRaises(VersionError, VersionRange, s) invalid_syntax = [ "<", # less than the empty version "><", # both greater and less than empty version ">3>4", # both are lower bounds "<3<4", # both are upper bounds "<4>3", # upper bound before lower ",<4", # leading comma "4+,", # trailing comma "1>=", # pre-lower-op in post "+1", # post-lower-op in pre "4<", # pre-upper-op in post "1+<2<3" # more than two bounds ] for s in invalid_syntax: self.assertRaises(VersionError, VersionRange, s) # test simple logic self.assertTrue(VersionRange("").is_any()) self.assertTrue(VersionRange("2+<4").bounded()) self.assertTrue(VersionRange("2+").lower_bounded()) self.assertTrue(not VersionRange("2+").upper_bounded()) self.assertTrue(not VersionRange("2+").bounded()) self.assertTrue(VersionRange("<2").upper_bounded()) self.assertTrue(not VersionRange("<2").lower_bounded()) self.assertTrue(not VersionRange("<2").bounded()) # test range from version(s) v = Version("3") self.assertTrue(VersionRange.from_version(v, "eq") == VersionRange("==3")) self.assertTrue(VersionRange.from_version(v, "gt") == VersionRange(">3")) self.assertTrue(VersionRange.from_version(v, "gte") == VersionRange("3+")) self.assertTrue(VersionRange.from_version(v, "lt") == VersionRange("<3")) self.assertTrue(VersionRange.from_version(v, "lte") == VersionRange("<=3")) range1 = VersionRange.from_version(Version("2"), "gte") range2 = VersionRange.from_version(Version("4"), "lte") _eq(str(range1 & range2), "2..4") v2 = Version("6.0") v3 = Version("4") self.assertTrue(VersionRange.from_versions([v, v2, v3]) == VersionRange("==3|==4|==6.0")) # test behaviour in sets def _eq2(a, b): _print("'%s' == '%s'" % (a, b)) self.assertTrue(a == b) a = VersionRange("1+<=2.5") b = VersionRange("1..2.5") c = VersionRange(">=5") d = VersionRange(">6.1.0") e = VersionRange("3.2") _eq2(set([a]) - set([a]), set()) _eq2(set([a]) - set([b]), set()) _eq2(set([a, a]) - set([a]), set()) _eq2(set([b, c, d, e]) - set([a]), set([c, d, e])) _eq2(set([b, c, e]) | set([c, d]), set([b, c, d, e])) _eq2(set([b, c]) & set([c, d]), set([c]))