diff --git a/firanka/series/range.py b/firanka/series/range.py index 888845bb721836851d341f88381eaa4218134758..c3cd8158635daed17edf1e7d460e45ac4952791b 100644 --- a/firanka/series/range.py +++ b/firanka/series/range.py @@ -20,65 +20,55 @@ def pre_range(fun): class Range(object): """ - Range of real numbers + Range of real numbers. Immutable. """ - def __from_str(self, rs): - if rs[0] not in '<(': raise ValueError('Must start with ( or <') - if rs[-1] not in '>)': raise ValueError('Must end with ) or >') - if ';' not in rs: raise ValueError('Separator ; required') - - start, stop = rs[1:-1].split(';') - start = float(start) - stop = float(stop) - return float(start), float(stop), rs[0] == '<', rs[-1] == '>' - - def __from_range(self, rs): - return rs.start, rs.stop, rs.lend_inclusive, rs.rend_inclusive def __init__(self, *args): if len(args) == 1: rs, = args - args = { - True: self.__from_range, - False: self.__from_str - }[isinstance(rs, type(self))](rs) + if isinstance(rs, type(self)): + args = rs.start, rs.stop, rs.left_inc, rs.right_inc + else: + if rs[0] not in '<(': raise ValueError('Must start with ( or <') + if rs[-1] not in '>)': raise ValueError('Must end with ) or >') + if ';' not in rs: raise ValueError('Separator ; required') - q = lambda a, b: args[a] and math.isinf(args[b]) + start, stop = rs[1:-1].split(';') + args = float(start), float(stop), rs[0] == '<', rs[-1] == '>' - if q(2, 0) or q(3, 1): + q = lambda a, b, args: args[a] and math.isinf(args[b]) + + if q(2, 0, args) or q(3, 1, args): raise ValueError('Set with sharp closing but infinity set') - self.start, self.stop, self.lend_inclusive, self.rend_inclusive = args + print(args) + self.start, self.stop, self.left_inc, self.right_inc = args def __contains__(self, x): if x == self.start: - return self.lend_inclusive + return self.left_inc if x == self.stop: - return self.rend_inclusive + return self.right_inc return self.start < x < self.stop def is_empty(self): - return (self.start == self.stop) and (not self.lend_inclusive) and ( - not self.rend_inclusive) + print(self.start, self.stop, self.left_inc, self.right_inc) + return (self.start == self.stop) and not (self.left_inc or self.right_inc) def __len__(self): return self.stop - self.start def __repr__(self): - return 'Range(%s, %s, %s, %s)' % (repr(self.start), repr(self.stop), repr(self.lend_inclusive), repr(self.rend_inclusive)) - - def __bool__(self): - """True if not empty""" - return not self.is_empty() + return 'Range(%s, %s, %s, %s)' % (repr(self.start), repr(self.stop), repr(self.left_inc), repr(self.right_inc)) def __str__(self): return '%s%s;%s%s' % ( - '<' if self.lend_inclusive else '(', + '<' if self.left_inc else '(', self.start, self.stop, - '>' if self.rend_inclusive else ')', + '>' if self.right_inc else ')', ) @pre_range @@ -91,29 +81,31 @@ class Range(object): if (self.stop < y.start) or (y.stop < y.start): return EMPTY_RANGE - if self.stop == y.start and not (self.rend_inclusive and y.lend_inclusive): + if self.stop == y.start and not (self.right_inc and y.left_inc): return EMPTY_RANGE if self.start == y.start: start = self.start - lend_inclusive = self.lend_inclusive or y.lend_inclusive + left_inc = self.left_inc or y.left_inc else: start = y.start - lend_inclusive = y.lend_inclusive + left_inc = y.left_inc if self.stop == y.stop: stop = self.stop - rend_inclusive = self.rend_inclusive or y.rend_inclusive + right_inc = self.right_inc or y.right_inc else: p, q = (self, y) if self.stop < y.stop else (y, self) stop = p.stop - rend_inclusive = p.rend_inclusive and (stop in q) + right_inc = p.right_inc and (stop in q) - return Range(start, stop, lend_inclusive, rend_inclusive) + return Range(start, stop, left_inc, right_inc) @pre_range def __eq__(self, other): - return self.start == other.start and self.stop == other.stop and self.lend_inclusive == other.lend_inclusive and self.rend_inclusive == other.rend_inclusive + if self.is_empty() and other.is_empty(): + return True + return self.start == other.start and self.stop == other.stop and self.left_inc == other.left_inc and self.right_inc == other.right_inc def __hash__(self): return hash(self.start) ^ hash(self.stop) diff --git a/tests/test_series/test_range.py b/tests/test_series/test_range.py index c7b2ff020725494b4daea459b3a2eecbd00f5781..852239f9f59454e510e3b3fd5951a57ea07145c2 100644 --- a/tests/test_series/test_range.py +++ b/tests/test_series/test_range.py @@ -1,13 +1,10 @@ # coding=UTF-8 from __future__ import print_function, absolute_import, division -import six import unittest from firanka.series import Range - class TestRange(unittest.TestCase): - def do_intersect(self, a, b, val): if type(val) == bool: if bool(Range(a).intersection(b)) != val: @@ -19,10 +16,14 @@ class TestRange(unittest.TestCase): self.assertEqual(Range(b).intersection(a), Range(val)) def test_isempty(self): - self.assertFalse(Range(-1,-1,False,False)) - self.assertTrue(Range(-1,-1,False,True)) - self.assertTrue(Range(-1,-1,False,False).is_empty()) - self.assertFalse(Range(-1,-1,False,True).is_empty()) + def tf(r, p): + s = Range(r) + self.assertEqual(s, r) + self.assertEqual(s.is_empty(), not p) + + tf(Range(-1,-1,False,False), False) + tf(Range(-1,-1,False,True), True) + self.assertEqual(Range(0,0,False,False), Range(2,2,False,False)) def test_intersection(self): self.do_intersect(Range(-10, -1, True, True), '<2;3>', False)