def test_replace(): i = I.open(-I.inf, I.inf) assert i.replace(lower=lambda v: 1, upper=lambda v: 1) == I.open(-I.inf, I.inf) assert i.replace(lower=lambda v: 1, upper=lambda v: 2, ignore_inf=False) == I.open(1, 2) assert I.empty().replace(left=I.CLOSED, right=I.CLOSED) == I.empty() assert I.empty().replace(lower=1, upper=2) == I.open(1, 2) assert I.empty().replace(lower=lambda v: 1, upper=lambda v: 2) == I.empty() assert I.empty().replace(lower=lambda v: 1, upper=lambda v: 2, ignore_inf=False) == I.open(1, 2) i = I.closed(0, 1) | I.open(2, 3) assert i.replace() == i assert i.replace(I.OPEN, -1, 4, I.OPEN) == I.openclosed(-1, 1) | I.open(2, 4) assert i.replace(lower=2) == I.closedopen(2, 3) assert i.replace(upper=1) == I.closedopen(0, 1) assert i.replace(lower=5) == I.empty() assert i.replace(upper=-5) == I.empty() assert i.replace( left=lambda v: not v, lower=lambda v: v - 1, upper=lambda v: v + 1, right=lambda v: not v) == I.openclosed(-1, 1) | I.openclosed(2, 4) assert I.empty().replace(lower=2, upper=4) == I.open(2, 4)
def test_from_string_customized(): i1, i2, i3, i4 = '<"0"-"1">', '<!"0"-"1">', '<"0"-"1"!>', '<!"0"-"1"!>' params = { 'conv': lambda s: int(s[1:-1]), 'disj': ' or ', 'sep': '-', 'left_open': '<!', 'left_closed': '<', 'right_open': '!>', 'right_closed': '>', 'pinf': r'\+oo', 'ninf': '-oo', } assert I.from_string(i1, **params) == I.closed(0, 1) assert I.from_string(i2, **params) == I.openclosed(0, 1) assert I.from_string(i3, **params) == I.closedopen(0, 1) assert I.from_string(i4, **params) == I.open(0, 1) assert I.from_string('<!!>', **params) == I.empty() assert I.from_string('<"1">', **params) == I.singleton(1) assert I.from_string('<!-oo-"1">', **params) == I.openclosed(-I.inf, 1) assert I.from_string('<"1"-+oo!>', **params) == I.closedopen(1, I.inf) assert I.from_string('<"0"-"1"> or <"2"-"3">', **params) == I.closed(0, 1) | I.closed(2, 3)
def test_to_string_customized(): i1, i2, i3, i4 = I.closed(0, 1), I.openclosed(0, 1), I.closedopen(0, 1), I.open(0, 1) params = { 'disj': ' or ', 'sep': '-', 'left_open': '<!', 'left_closed': '<', 'right_open': '!>', 'right_closed': '>', 'conv': lambda s: '"{}"'.format(s), 'pinf': '+oo', 'ninf': '-oo', } assert I.to_string(i1, **params) == '<"0"-"1">' assert I.to_string(i2, **params) == '<!"0"-"1">' assert I.to_string(i3, **params) == '<"0"-"1"!>' assert I.to_string(i4, **params) == '<!"0"-"1"!>' assert I.to_string(I.empty(), **params) == '<!!>' assert I.to_string(I.singleton(1), **params) == '<"1">' assert I.to_string(I.openclosed(-I.inf, 1), **params) == '<!-oo-"1">' assert I.to_string(I.closedopen(1, I.inf), **params) == '<"1"-+oo!>' assert I.to_string(I.closed(0, 1) | I.closed(2, 3), **params) == '<"0"-"1"> or <"2"-"3">'
def test_interval_constraints(): tests = { I.closedopen(Version('1.0.0'), Version('3.0.0')): { 'strict': False, 'bounded': (True, True), 'soft': (False, True, True), 'hard': (True, True, True), }, I.closedopen(Version('1.0.0'), Version('3.0.0')) | I.singleton(Version('4.0.0')): { 'strict': False, 'bounded': (True, True), 'soft': (False, False, False), 'hard': (True, True, True), }, I.closed(Version('1.0.0'), Version('2.0.0')) | I.closedopen(Version('3.0.0'), Version('3.1.0')): { 'strict': False, 'bounded': (True, True), 'soft': (False, False, True), 'hard': (True, True, True), }, I.closed(Version('1.0.0'), Version('2.0.0')) | I.closed(Version('3.0.0'), Version('3.1.0')): { 'strict': False, 'bounded': (True, True), 'soft': (False, False, True), 'hard': (True, True, True), }, } for constraint, expected in tests.items(): assert strict(constraint) == expected['strict'] assert (lower_bounded(constraint), upper_bounded(constraint)) == expected['bounded'] assert (allows_major(constraint), allows_minor(constraint), allows_patch(constraint)) == expected['soft'] assert (allows_major(constraint, soft=False), allows_minor(constraint, soft=False), allows_patch(constraint, soft=False)) == expected['hard']
def test_union(): assert I.closed(1, 2).to_atomic() | I.closed(1, 2).to_atomic() == I.closed(1, 2).to_atomic() assert I.closed(1, 4).to_atomic() | I.closed(2, 3).to_atomic() == I.closed(1, 4).to_atomic() assert I.closed(1, 2).to_atomic() | I.closed(2, 3).to_atomic() == I.closed(2, 3).to_atomic() | I.closed(1, 2).to_atomic() assert I.closed(1, 2).to_atomic() | I.closed(3, 4).to_atomic() == I.closed(1, 2) | I.closed(3, 4) assert I.closed(1, 2) | I.closed(1, 2) == I.closed(1, 2) assert I.closed(1, 4) | I.closed(2, 3) == I.closed(2, 3) | I.closed(1, 4) assert I.closed(1, 4) | I.closed(2, 3) == I.closed(1, 4) assert I.closed(1, 4) | I.closed(2, 3).to_atomic() == I.closed(1, 4) assert I.closed(1, 4) | I.closed(2, 3).to_atomic() == I.closed(2, 3).to_atomic() | I.closed(1, 4) assert I.closed(1, 2) | I.open(2, 3) == I.closedopen(1, 3) assert I.closed(1, 3) | I.closed(2, 4) == I.closed(1, 4) assert I.closed(1, 2) | I.closed(2, 3) == I.closed(2, 3) | I.closed(1, 2) assert I.closedopen(1, 2) | I.closed(2, 3) == I.closed(1, 3) assert I.open(1, 2) | I.closed(2, 4) == I.openclosed(1, 4) assert I.closed(1, 2) | I.closed(3, 4) != I.closed(1, 4) assert (I.closed(1, 2) | I.closed(3, 4) | I.closed(2, 3)).is_atomic() assert I.closed(1, 2) | I.closed(3, 4) | I.closed(2, 3) == I.closed(1, 4) assert I.closed(1, 2) | I.closed(0, 4) == I.closed(0, 4) assert (I.closed(0, 1) | I.closed(2, 3) | I.closed(1, 2)).is_atomic() assert I.closed(0, 1) | I.closed(2, 3) | I.closed(1, 2) == I.closed(0, 3) assert I.closed(0, 1) | I.empty() == I.closed(0, 1)
def read_memory_fast(s, module_list): module_list = sorted(module_list) # Get list of available address ranges for LSASS pslist = s.plugins.pslist(proc_regex='lsass.exe') task = next(pslist.filter_processes()) addr_space = task.get_process_address_space() max_memory = s.GetParameter("highest_usermode_address") mem_list = sorted([(run.start, run.end) for run in addr_space.get_address_ranges(end=max_memory) ]) # Enumerate modules, find "holes" that need zero filling filling = I.empty() for a, mod_start, size in module_list: d = I.IntervalDict() mod = I.closedopen(mod_start, mod_start + size) d[mod] = 'fill' # What parts of the module are available? for start, end in mem_list: mem = I.closedopen(start, end) if mem & mod != I.empty(): d[mem] = 'mem' if start > mod_start + size: break filling |= d.find('fill') # What to read, what to zero fill operations = [] for x in list(filling): operations.append((x.lower, x.upper, 'pad')) for start, end in mem_list: operations.append((start, end, 'mem')) # Read & fill memoryinfo_list = [] memory64_list = [] for start, end, op in sorted(operations): size = end - start mi = dict(BaseAddress=start, AllocationBase=0, AllocationProtect=0, RegionSize=size, Protect=0) mi['State'] = 0 mi['Type'] = 0 memoryinfo_list.append(mi) if op == 'fill': #data = b'\x00'*size # Attempt to read these anyway. Rekall will fill with zeros if the read fails data = addr_space.read(start, size) else: data = addr_space.read(start, size) memory64_list.append((start, size, data)) return memoryinfo_list, memory64_list
def constraint(self, op, version=None): if version is None: version = op op = '*' major, minor, patch = version if op == '*': if major == '*': return I.closedopen(Version.FIRST, I.inf) elif minor == '*': return minor_interval(Version(major, 0, 0)) elif patch == '*': return patch_interval(Version(major, minor, 0)) else: # Equivalent to ^x.y.z op = '^' if op == '^': if minor is None: # ^1 := >=1.0.0 <2.0.0 # ^0 := >=0.0.0 <1.0.0 return minor_interval(Version(major, 0, 0)) elif patch is None: # ^1.2 := >=1.2.0 <2.0.0 # ^0.0 := >=0.0.0 <0.1.0 if major == 0: return patch_interval(Version(major, minor, 0)) else: return minor_interval(Version(major, minor, 0)) else: # ^1.2.3 := >=1.2.3 <2.0.0 # ^0.2.3 := >=0.2.3 <0.3.0 # ^0.0.3 := >=0.0.3 <0.0.4 if major == 0: if minor == 0: return I.closedopen(Version(0, 0, patch), Version(0, 0, patch + 1)) else: return patch_interval(Version(0, minor, patch)) else: return minor_interval(Version(major, minor, patch)) elif op == '~': if minor is None: # ~1 := >=1.0.0 <2.0.0 return minor_interval(Version(major, 0, 0)) elif patch is None: # ~1.2 := >=1.2.0 <1.3.0 return patch_interval(Version(major, minor, 0)) else: # ~1.2.3 := >=1.2.3 <1.3.0 return patch_interval(Version(major, minor, patch)) else: # =, >=, >, <=, <, != minor = 0 if minor is None else minor patch = 0 if patch is None else patch return comparator_interval(op, Version(major, minor, patch)) assert False, (op, version)
def test_strict_constraints(): assert strict(I.closed(Version('1.0.0'), Version('1.0.0'))) assert strict(I.closedopen(Version('1.0.0'), Version('1.0.1'))) assert strict(I.closedopen(Version('1.0.0'), Version('1.0.1'))) assert not strict(I.closed(Version('1.0.0'), Version('1.0.1'))) assert not strict(I.closed(Version('1.0.0'), Version('1.1.0'))) assert not strict(I.closed(Version('1.0.0'), Version('2.0.0'))) assert not strict(I.closed(Version('1.0.0'), I.inf))
def test_to_data(): assert I.to_data(I.closedopen(2, 3)) == [(I.CLOSED, 2, 3, I.OPEN)] assert I.to_data(I.openclosed(2, I.inf)) == [(I.OPEN, 2, float('inf'), I.OPEN)] assert I.to_data(I.closed(-I.inf, 2)) == [(I.OPEN, float('-inf'), 2, I.CLOSED)] assert I.to_data(I.empty()) == [(I.OPEN, float('inf'), float('-inf'), I.OPEN)] i = I.openclosed(-I.inf, 4) | I.closedopen(6, I.inf) assert I.to_data(i) == [(I.OPEN, float('-inf'), 4, I.CLOSED), (I.CLOSED, 6, float('inf'), I.OPEN)] assert I.to_data(i, conv=str, pinf='highest', ninf='lowest') == [(I.OPEN, 'lowest', '4', I.CLOSED), (I.CLOSED, '6', 'highest', I.OPEN)]
def test_complement(): assert ~I.closed(1, 2) == I.open(-I.inf, 1) | I.open(2, I.inf) assert ~I.open(1, 2) == I.openclosed(-I.inf, 1) | I.closedopen(2, I.inf) intervals = [I.closed(0, 1), I.open(0, 1), I.openclosed(0, 1), I.closedopen(0, 1)] for interval in intervals: assert ~(~interval) == interval assert ~I.open(1, 1) == I.open(-I.inf, I.inf) assert (~I.closed(-I.inf, I.inf)).is_empty() assert ~I.empty() == I.open(-I.inf, I.inf)
def test_from_data(): assert I.from_data([(I.CLOSED, 2, 3, I.OPEN)]) == I.closedopen(2, 3) assert I.from_data([(I.OPEN, 2, float('inf'), I.OPEN)]) == I.openclosed(2, I.inf) assert I.from_data([(I.OPEN, float('-inf'), 2, I.CLOSED)]) == I.closed(-I.inf, 2) assert I.from_data([]) == I.empty() d = [(I.OPEN, float('-inf'), 4, I.CLOSED), (I.CLOSED, 6, float('inf'), I.OPEN)] assert I.from_data(d) == I.openclosed(-I.inf, 4) | I.closedopen(6, I.inf) d = [(I.OPEN, 'lowest', '4', I.CLOSED), (I.CLOSED, '6', 'highest', I.OPEN)] assert I.from_data(d, conv=int, pinf='highest', ninf='lowest') == I.openclosed(-I.inf, 4) | I.closedopen(6, I.inf)
def test_intervaldict_iterators(): d = I.IntervalDict([(I.closedopen(0, 1), 0), (I.closedopen(1, 3), 1), (I.singleton(3), 2)]) assert d.keys() == [I.closedopen(0, 1), I.closedopen(1, 3), I.singleton(3)] assert d.domain() == I.closed(0, 3) assert d.values() == [0, 1, 2] assert d.items() == list(zip(d.keys(), d.values())) assert list(d) == d.keys() # Iterators on empty assert I.IntervalDict().values() == [] assert I.IntervalDict().items() == [] assert I.IntervalDict().keys() == [] assert I.IntervalDict().domain() == I.empty()
def test_overlaps(): # Overlaps should reject non supported types with pytest.raises(TypeError): I.closed(0, 1).to_atomic().overlaps(1) with pytest.raises(TypeError): I.closed(0, 1).overlaps(1) assert I.closed(0, 1).overlaps(I.closed(0, 1)) assert I.closed(0, 1).overlaps(I.open(0, 1)) assert I.open(0, 1).overlaps(I.closed(0, 1)) assert I.closed(0, 1).overlaps(I.openclosed(0, 1)) assert I.closed(0, 1).overlaps(I.closedopen(0, 1)) assert I.closed(1, 2).overlaps(I.closed(2, 3)) assert I.closed(1, 2).overlaps(I.closedopen(2, 3)) assert I.openclosed(1, 2).overlaps(I.closed(2, 3)) assert I.openclosed(1, 2).overlaps(I.closedopen(2, 3)) assert not I.closed(0, 1).overlaps(I.closed(3, 4)) assert not I.closed(3, 4).overlaps(I.closed(0, 1)) assert not I.closed(0, 1).overlaps(I.open(1, 2)) assert not I.closed(0, 1).overlaps(I.openclosed(1, 2)) assert not I.closedopen(0, 1).overlaps(I.closed(1, 2)) assert not I.closedopen(0, 1).overlaps(I.closedopen(1, 2)) assert not I.closedopen(0, 1).overlaps(I.openclosed(1, 2)) assert not I.closedopen(0, 1).overlaps(I.open(1, 2)) assert not I.open(0, 1).overlaps(I.open(1, 2)) assert not I.empty().overlaps(I.open(-I.inf, I.inf)) assert not I.open(-I.inf, I.inf).overlaps(I.empty())
def comparator_interval(op, version): if op == '=': return I.singleton(version) if op == '<': return I.closedopen(Version.FIRST, version) if op == '<=': return I.closed(Version.FIRST, version) if op == '>': return I.open(version, I.inf) if op == '>=': return I.closedopen(version, I.inf) if op == '!=': return I.closedopen(Version.FIRST, version) | I.openclosed( version, I.inf)
def test_overlaps_permissive(): assert I.closed(0, 1).overlaps(I.closed(0, 1), permissive=True) assert I.closed(0, 1).overlaps(I.open(0, 1), permissive=True) assert I.open(0, 1).overlaps(I.closed(0, 1), permissive=True) assert I.closed(0, 1).overlaps(I.openclosed(0, 1), permissive=True) assert I.closed(0, 1).overlaps(I.closedopen(0, 1), permissive=True) assert I.closed(1, 2).overlaps(I.closed(2, 3), permissive=True) assert I.closed(1, 2).overlaps(I.closedopen(2, 3), permissive=True) assert I.openclosed(1, 2).overlaps(I.closed(2, 3), permissive=True) assert I.openclosed(1, 2).overlaps(I.closedopen(2, 3), permissive=True) assert not I.closed(0, 1).overlaps(I.closed(3, 4), permissive=True) assert not I.closed(3, 4).overlaps(I.closed(0, 1), permissive=True) assert I.closed(0, 1).overlaps(I.open(1, 2), permissive=True) assert I.closed(0, 1).overlaps(I.openclosed(1, 2), permissive=True) assert I.closedopen(0, 1).overlaps(I.closed(1, 2), permissive=True) assert I.closedopen(0, 1).overlaps(I.closedopen(1, 2), permissive=True) assert not I.closedopen(0, 1).overlaps(I.openclosed(1, 2), permissive=True) assert not I.closedopen(0, 1).overlaps(I.open(1, 2), permissive=True) assert not I.open(0, 1).overlaps(I.open(1, 2), permissive=True) assert not I.empty().overlaps(I.open(-I.inf, I.inf), permissive=True) assert not I.open(-I.inf, I.inf).overlaps(I.empty(), permissive=True)
def test_iterate(): # Default parameters assert list(I.iterate(I.closed(0, 2), incr=1)) == [0, 1, 2] assert list(I.iterate(I.closedopen(0, 2), incr=1)) == [0, 1] assert list(I.iterate(I.openclosed(0, 2), incr=1)) == [1, 2] assert list(I.iterate(I.open(0, 2), incr=1)) == [1] assert list(I.iterate(I.open(0, 2.5), incr=1)) == [1, 2] # Empty intervals or iterations assert list(I.iterate(I.empty(), incr=1)) == [] assert list(I.iterate(I.open(0, 1), incr=1)) == [] # Infinities with pytest.raises(ValueError): list(I.iterate(I.openclosed(-I.inf, 2), incr=1)) gen = I.iterate(I.closedopen(0, I.inf), incr=1) assert next(gen) == 0 assert next(gen) == 1 assert next(gen) == 2 # and so on # Unions assert list(I.iterate(I.closed(0, 1) | I.closed(5, 6), incr=1)) == [0, 1, 5, 6] assert list(I.iterate(I.closed(0, 1) | I.closed(2.5, 4), incr=1)) == [0, 1, 2.5, 3.5] assert list(I.iterate(I.open(0, 1) | I.open(1, 2), incr=1)) == [] assert list(I.iterate(I.open(0.5, 1) | I.open(1, 3), incr=1)) == [2] # Step assert list(I.iterate(I.closed(0, 6), incr=2)) == [0, 2, 4, 6] assert list(I.iterate(I.closed(0, 6), incr=4)) == [0, 4] assert list(I.iterate(I.closed(0, 6), incr=lambda x: x + 2)) == [0, 2, 4, 6] # Base assert list(I.iterate(I.closed(0.4, 2), incr=1, base=lambda x: round(x))) == [1, 2] assert list(I.iterate(I.closed(0.6, 2), incr=1, base=lambda x: round(x))) == [1, 2] # Reversed assert list(I.iterate(I.closed(0, 1), incr=1, reverse=True)) == [1, 0] assert list(I.iterate(I.open(0, 3), incr=1, reverse=True)) == [2, 1] assert list(I.iterate(I.closed(0, 1), incr=0.5, reverse=True)) == [1, 0.5, 0] assert list(I.iterate(I.closed(0, 2), incr=1, base=lambda x: x-1, reverse=True)) == [1, 0] assert list(I.iterate(I.closed(0, 2) | I.closed(4, 5), incr=1, reverse=True)) == [5, 4, 2, 1, 0] with pytest.raises(ValueError): list(I.iterate(I.closedopen(0, I.inf), incr=1, reverse=True)) gen = I.iterate(I.openclosed(-I.inf, 2), incr=1, reverse=True) assert next(gen) == 2 assert next(gen) == 1 assert next(gen) == 0 # and so on
def test_to_string(): i1, i2, i3, i4 = I.closed(0, 1), I.openclosed(0, 1), I.closedopen(0, 1), I.open(0, 1) assert I.to_string(i1) == '[0,1]' assert I.to_string(i2) == '(0,1]' assert I.to_string(i3) == '[0,1)' assert I.to_string(i4) == '(0,1)' assert I.to_string(I.empty()) == '()' assert I.to_string(I.singleton(1)) == '[1]' assert I.to_string(I.openclosed(-I.inf, 1)) == '(-inf,1]' assert I.to_string(I.closedopen(1, I.inf)) == '[1,+inf)' assert I.to_string(I.closed(0, 1) | I.closed(2, 3)) == '[0,1] | [2,3]'
def caret(self, version): major, minor, patch = version # Desugar * major = None if major == '*' else major minor = None if minor == '*' else minor patch = None if patch == '*' else patch if major == 0: if minor is None: # ^0.x := >=0.0.0 <1.0.0 return minor_interval(Version(0, 0, 0)) elif patch is None: # ^0.0.x := >=0.0.0 <0.1.0 # ^0.0 := >=0.0.0 <0.1.0 # ^0.1.x := >=0.1.0 <0.2.0 return patch_interval(Version(0, minor or 0, 0)) else: if minor == 0: # ^0.0.3 := >=0.0.3 <0.0.4 return I.closedopen(Version(0, 0, patch), Version(0, 0, patch + 1)) else: # ^0.2.3 := >=0.2.3 <0.3.0 return patch_interval(Version(0, minor, patch)) else: # ^1.x := >=1.0.0 <2.0.0 # ^1.2.x := >=1.2.0 <2.0.0 # ^1.2.3 := >=1.2.3 <2.0.0 return minor_interval(Version(major, minor or 0, patch or 0))
def test_creation(): assert I.closed(0, 1) == I.AtomicInterval(I.CLOSED, 0, 1, I.CLOSED) assert I.open(0, 1) == I.AtomicInterval(I.OPEN, 0, 1, I.OPEN) assert I.openclosed(0, 1) == I.AtomicInterval(I.OPEN, 0, 1, I.CLOSED) assert I.closedopen(0, 1) == I.AtomicInterval(I.CLOSED, 0, 1, I.OPEN) assert I.closed(-I.inf, I.inf) == I.open(-I.inf, I.inf) assert I.singleton(2) == I.closed(2, 2) assert I.Interval() == I.open(0, 0) assert I.empty() == I.Interval() assert I.closed(3, -3) == I.empty() assert I.openclosed(3, 3) == I.empty() # I.empty() is a singleton assert I.empty() is I.empty() assert I.Interval(I.closed(0, 1).to_atomic()) == I.closed(0, 1) assert I.Interval(I.closed(0, 1)) == I.closed(0, 1) assert I.Interval(I.closed(0, 1).to_atomic(), I.closed(2, 3)) == I.closed(0, 1) | I.closed(2, 3) assert I.Interval(I.closed(0, 1) | I.closed(2, 3)) == I.closed(0, 1) | I.closed(2, 3) with pytest.raises(TypeError): I.Interval(1)
def test_case_from_real_life(): part = generate_trivial_part(5) part.node[0][interval] = i.closed(5, 5) part.node[1][interval] = i.closed(7, 8) part.node[2][interval] = i.closedopen(9, i.inf) part.node[3][interval] = i.closedopen(9, i.inf) part.node[4][interval] = i.closedopen(9, i.inf) part.node[5][interval] = i.closed(5, 5) rule = nx.complete_graph(3) rule.node[0][interval] = i.closed(6, 8) rule.node[1][interval] = i.closedopen(7, i.inf) rule.node[2][interval] = i.closedopen(9, i.inf) assert_true(check_apply_unambiguously_at_rotation(part, rule, 0)) assert_true(check_apply_unambiguously(part, rule))
def test_emptiness(): assert I.openclosed(1, 1).is_empty() assert I.closedopen(1, 1).is_empty() assert I.open(1, 1).is_empty() assert not I.closed(1, 1).is_empty() assert I.Interval().is_empty() assert I.empty().is_empty()
def test_intersection(): assert I.closed(0, 1) & I.closed(0, 1) == I.closed(0, 1) assert I.closed(0, 1) & I.closed(0, 1).to_atomic() == I.closed(0, 1) assert I.closed(0, 1) & I.open(0, 1) == I.open(0, 1) assert I.openclosed(0, 1) & I.closedopen(0, 1) == I.open(0, 1) assert (I.closed(0, 1) & I.closed(2, 3)).is_empty() assert I.closed(0, 1) & I.empty() == I.empty()
def is_run_pair_contained(self, input_run_pair): (input_offset, input_length) = input_run_pair if input_offset is None: return None if input_length is None: return None input_interval = I.closedopen(input_offset, input_offset + input_length) return input_interval in self.intervals
def build_interval_draft4(self): if self.exclusiveMinimum and self.exclusiveMaximum: self.interval = I.open(self.minimum, self.maximum) elif self.exclusiveMinimum: self.interval = I.openclosed(self.minimum, self.maximum) elif self.exclusiveMaximum: self.interval = I.closedopen(self.minimum, self.maximum) else: self.interval = I.closed(self.minimum, self.maximum)
def test_from_string(): i1, i2, i3, i4 = '[0,1]', '(0,1]', '[0,1)', '(0,1)' assert I.from_string(i1, int) == I.closed(0, 1) assert I.from_string(i2, int) == I.openclosed(0, 1) assert I.from_string(i3, int) == I.closedopen(0, 1) assert I.from_string(i4, int) == I.open(0, 1) assert I.from_string('()', int) == I.empty() assert I.from_string('[1]', int) == I.singleton(1) assert I.from_string('(-inf,1]', int) == I.openclosed(-I.inf, 1) assert I.from_string('[1,+inf)', int) == I.closedopen(1, I.inf) assert I.from_string('[0,1] | [2,3]', int) == I.closed(0, 1) | I.closed(2, 3) with pytest.raises(Exception): I.from_string('[1,2]', None)
def test_difference(): assert I.closed(1, 4) - I.closed(1, 3) == I.openclosed(3, 4) assert I.closed(1, 4) - I.closed(1, 3).to_atomic() == I.openclosed(3, 4) assert I.closed(1, 4).to_atomic() - I.closed( 1, 3).to_atomic() == I.openclosed(3, 4) assert (I.closed(1, 4) - I.closed(1, 4)).is_empty() assert I.closed(0, 1) - I.closed(2, 3) == I.closed(0, 1) assert I.closed(0, 4) - I.closed(2, 3) == I.closedopen( 0, 2) | I.openclosed(3, 4)
def hyphen(self, left, right): lmajor, lminor, lpatch = left rmajor, rminor, rpatch = right lminor = 0 if lminor is None else lminor lpatch = 0 if lpatch is None else lpatch if rminor is None: # 1.0.0 - 2 := >=1.0.0 <3.0.0 because "2" becames "2.*.*" return I.closedopen(Version(lmajor, lminor, lpatch), Version(rmajor + 1, 0, 0)) elif rpatch is None: # 1.0.0 - 2.0 := >=1.0.0 <2.1 because "2.0" becames "2.0.*" return I.closedopen(Version(lmajor, lminor, lpatch), Version(rmajor, rminor + 1, 0)) else: # Inclusive return I.closed(Version(lmajor, lminor, lpatch), Version(rmajor, rminor, rpatch))
def test_overlaps(): # Overlaps should reject non supported types with pytest.raises(TypeError): I.closed(0, 1).to_atomic().overlaps(1) with pytest.raises(TypeError): I.closed(0, 1).overlaps(1) assert I.closed(0, 1).overlaps(I.closed(0, 1)) assert I.closed(0, 1).overlaps(I.open(0, 1)) assert I.open(0, 1).overlaps(I.closed(0, 1)) assert I.closed(0, 1).overlaps(I.openclosed(0, 1)) assert I.closed(0, 1).overlaps(I.closedopen(0, 1)) assert I.closed(1, 2).overlaps(I.closed(2, 3)) assert I.closed(1, 2).overlaps(I.closedopen(2, 3)) assert I.openclosed(1, 2).overlaps(I.closed(2, 3)) assert I.openclosed(1, 2).overlaps(I.closedopen(2, 3)) assert not I.closed(0, 1).overlaps(I.closed(3, 4)) assert not I.closed(3, 4).overlaps(I.closed(0, 1)) assert not I.closed(0, 1).overlaps(I.open(1, 2)) assert not I.closed(0, 1).overlaps(I.openclosed(1, 2)) assert not I.closedopen(0, 1).overlaps(I.closed(1, 2)) assert not I.closedopen(0, 1).overlaps(I.closedopen(1, 2)) assert not I.closedopen(0, 1).overlaps(I.openclosed(1, 2)) assert not I.closedopen(0, 1).overlaps(I.open(1, 2)) assert not I.open(0, 1).overlaps(I.open(1, 2)) assert not I.empty().overlaps(I.open(-I.inf, I.inf)) assert not I.open(-I.inf, I.inf).overlaps(I.empty()) # https://github.com/AlexandreDecan/python-intervals/issues/13 assert not I.closed(0, 1).overlaps(I.openclosed(1, 2)) assert not I.closedopen(0, 1).overlaps(I.closed(1, 2)) assert not I.closed(1, 1).overlaps(I.openclosed(1, 2)) assert not I.closedopen(1, 1).overlaps(I.closed(1, 2)) assert not I.openclosed(1, 2).overlaps(I.closed(0, 1)) assert not I.openclosed(1, 2).overlaps(I.closed(1, 1)) assert I.open(0, 2).overlaps(I.open(0, 1)) assert I.open(0, 1).overlaps(I.open(0, 2))
def test_bounded_constraints(): assert upper_bounded(I.closed(Version('1.0.0'), Version('2.0.0'))) assert upper_bounded(I.closed(Version('1.0.0'), Version('1.0.0'))) assert upper_bounded(I.closed(Version('1.0.0'), Version('1.0.1'))) assert upper_bounded(I.closed(Version('1.0.0'), Version('1.1.0'))) assert upper_bounded(I.closedopen(Version('1.0.0'), Version('1.0.1'))) assert not upper_bounded(I.closed(Version('1.0.0'), I.inf)) assert lower_bounded(I.closed(Version('0.0.1'), Version('2.0.0'))) assert lower_bounded(I.closed(Version('0.0.2'), Version('2.0.0'))) assert not lower_bounded(I.closed(Version.FIRST, Version('2.0.0')))
def test_interval_to_atomic(): intervals = [I.closed(0, 1), I.open(0, 1), I.openclosed(0, 1), I.closedopen(0, 1)] for interval in intervals: assert interval == I.Interval(interval.to_atomic()) assert interval == interval.to_atomic() assert I.closed(0, 1) | I.closed(2, 3) != I.closed(0, 3) assert (I.closed(0, 1) | I.closed(2, 3)).to_atomic() == I.closed(0, 3) assert I.closed(0, 1).to_atomic() == I.closed(0, 1).enclosure() assert (I.closed(0, 1) | I.closed(2, 3)).enclosure() == I.closed(0, 3) assert I.empty().to_atomic() == I.AtomicInterval(False, I.inf, -I.inf, False)