コード例 #1
0
    def test_add_many_pairs(self):
        for a_low in range(0, 6):
            for a_high in range(0, 6):
                if a_low > a_high:
                    continue
                a_ranges = [
                    Range.closed(a_low, a_high),
                    Range.open_closed(a_low, a_high),
                    Range.closed_open(a_low, a_high),
                ]
                if a_low != a_high:
                    a_ranges.append(Range.open(a_low, a_high))

                for b_low in range(0, 6):
                    for b_high in range(0, 6):
                        if b_low > b_high:
                            continue
                        b_ranges = [
                            Range.closed(b_low, b_high),
                            Range.open_closed(b_low, b_high),
                            Range.closed_open(b_low, b_high),
                        ]
                        if b_low != b_high:
                            b_ranges.append(Range.open(b_low, b_high))
                        for a_range in a_ranges:
                            for b_range in b_ranges:
                                self._pair_test(a_range, b_range)
コード例 #2
0
 def test_range_containing1(self):
     range_set = RangeSet.create_mutable()
     range_set.add(Range.closed(3, 10))
     self.assertEqual(Range.closed(3, 10), range_set.range_containing(5))
     self.assertTrue(5 in range_set)
     self.assertIsNone(range_set.range_containing(1))
     self.assertFalse(1 in range_set)
コード例 #3
0
 def test_ignores_smaller_sharing_lower_bound(self):
     range_set = RangeSet.create_mutable()
     range_set.add(Range.closed(1, 6))
     range_set.add(Range.closed(1, 4))
     self._test_invariants(range_set)
     self.assertEqual(tuple([Range.closed(1, 6)]),
                      tuple(range_set.as_ranges()))
コード例 #4
0
 def test_add_all(self):
     range_set = RangeSet.create_mutable()
     range_set.add(Range.closed(3, 10))
     range_set.add_all(
         [Range.open(1, 3),
          Range.closed(5, 8),
          Range.closed(9, 11)])
     self.assertEqual(tuple(range_set.as_ranges()),
                      tuple([Range.open_closed(1, 11)]))
コード例 #5
0
 def test_len(self):
     self.assertEqual(0, len(RangeSet.create_mutable()))
     self.assertEqual(
         1, len(RangeSet.create_mutable().add(Range.closed(1, 2))))
     self.assertEqual(
         2,
         len(RangeSet.create_mutable().add(Range.closed(1, 2)).add(
             Range.open(3, 4))),
     )
コード例 #6
0
 def test_overlapping_keys_banned(self):
     with self.assertRaisesRegex(
             ValueError,
             "Some range keys are connected or overlapping. Overlapping keys "
             "will never be supported. Support for connected keys is tracked in "
             "https://github.com/isi-vista/vistautils/issues/37",
     ):
         (ImmutableRangeMap.builder().put(Range.closed(0, 2),
                                          0).put(Range.closed(1, 3),
                                                 1).build())
コード例 #7
0
 def test_integer(self):
     params = Parameters.from_mapping({"test_int": 5})
     self.assertEqual(5, params.integer("test_int"))
     self.assertEqual(2, params.integer("not_appearing", default=2))
     with self.assertRaisesRegex(ParameterError,
                                 "Invalid value for integer parameter"):
         params.integer("test_int", valid_range=Range.closed(1, 3))
     with self.assertRaisesRegex(ParameterError,
                                 "Invalid value for integer parameter"):
         params.integer("not_appearing",
                        default=2,
                        valid_range=Range.closed(10, 20))
コード例 #8
0
    def test_get_rightmost_containing_or_below(self):
        range_map = immutablerangemap((
            (Range.closed(-2, -1), 0),
            (Range.closed_open(0, 2), 1),
            # we don't do [0, 2), [2.1, 3] because they will coalesce
            # ditto for (4, 5] and (5.1, 7)
            (Range.closed(2.1, 3), 2),
            (Range.open_closed(4, 5), 3),
            (Range.open(5.1, 7), 4),
        ))

        # probe value is in the middle of a set
        # [2.1  ... *2.5* ... 3]
        self.assertEqual(2,
                         range_map.get_from_rightmost_containing_or_below(2.5))
        # probe value is at a closed upper limit
        # [2.1 .... *3*]
        self.assertEqual(2,
                         range_map.get_from_rightmost_containing_or_below(3.0))
        # probe value is at a closed lower limit
        # [*2.1* .... 3]
        self.assertEqual(2,
                         range_map.get_from_rightmost_containing_or_below(2.1))
        # probe value is at an open lower limit
        # [2.1 ... 3], (*4* ... 5]
        self.assertEqual(2,
                         range_map.get_from_rightmost_containing_or_below(4.0))
        # probe value is at an open upper limit
        # [0 ... *2.1*)
        self.assertEqual(1,
                         range_map.get_from_rightmost_containing_or_below(2.0))
        # probe value falls into a gap
        # [-2, -1] ... *-0.5* ... [0, 2)
        self.assertEqual(
            0, range_map.get_from_rightmost_containing_or_below(-0.5))
        # no range below
        # *-3* .... [-2,-1]
        self.assertIsNone(
            range_map.get_from_rightmost_containing_or_below(-3.0))
        # empty rangeset
        self.assertIsNone(
            immutablerangemap(
                ((Range.closed(1.0, 2.0),
                  1), )).get_from_rightmost_containing_or_below(0.0))
        # lowest range has open lower bound
        # (*1*,2)
        self.assertIsNone(
            immutablerangemap(
                ((Range.open(1.0, 2.0),
                  1), )).get_from_rightmost_containing_or_below(1.0))
コード例 #9
0
    def test_get_leftmost_containing_or_above(self):
        range_map = immutablerangemap((
            (Range.closed(-2, -1), 0),
            (Range.closed_open(0, 2), 1),
            # we don't do [0, 2), [2.1, 3] because they will coalesce
            # ditto for (4, 5] and (5.1, 7)
            (Range.closed(2.1, 3), 2),
            (Range.open_closed(4, 5), 3),
            (Range.open(5.1, 7), 4),
        ))

        # probe value is in the middle of a set
        # [2.1  ... *2.5* ... 3]
        self.assertEqual(2,
                         range_map.get_from_leftmost_containing_or_above(2.5))
        # probe value is at a closed upper limit
        # [2.1 .... *3*]
        self.assertEqual(2,
                         range_map.get_from_leftmost_containing_or_above(3.0))
        # probe value is at a closed lower limit
        # [*2.1* .... 3]
        self.assertEqual(2,
                         range_map.get_from_leftmost_containing_or_above(2.1))
        # probe value is at an open lower limit
        # [2 ... 3], (*4* ... 5]
        self.assertEqual(3,
                         range_map.get_from_leftmost_containing_or_above(4.0))
        # probe value is at an open upper limit
        # [0 ... *2*) [2.1, 3.0]
        self.assertEqual(2,
                         range_map.get_from_leftmost_containing_or_above(2.0))
        # probe value falls into a gap
        # [-2, -1] ... *-0.5* ... [0, 2)
        self.assertEqual(1,
                         range_map.get_from_leftmost_containing_or_above(-0.5))
        # no range above
        # (5.1 ... 7) ... *8*
        self.assertIsNone(range_map.get_from_leftmost_containing_or_above(8))
        # empty rangeset
        self.assertIsNone(
            immutablerangemap(
                ((Range.closed(1.0, 2.0),
                  1), )).get_from_leftmost_containing_or_above(3.0))
        # higher range has open upper bound
        # (1,*2*)
        self.assertIsNone(
            immutablerangemap(
                ((Range.open(1.0, 2.0),
                  1), )).get_from_leftmost_containing_or_above(2.0))
コード例 #10
0
    def test_encloses_closed(self):
        rng = Range.closed(2, 5)
        self.assertTrue(rng.encloses(rng))
        self.assertTrue(rng.encloses(Range.open(2, 5)))
        self.assertTrue(rng.encloses(Range.open_closed(2, 5)))
        self.assertTrue(rng.encloses(Range.closed_open(2, 5)))
        self.assertTrue(rng.encloses(Range.closed(3, 5)))
        self.assertTrue(rng.encloses(Range.closed(2, 4)))

        self.assertFalse(rng.encloses(Range.open(1, 6)))
        self.assertFalse(rng.encloses(Range.greater_than(3)))
        self.assertFalse(rng.encloses(Range.less_than(3)))
        self.assertFalse(rng.encloses(Range.at_least(3)))
        self.assertFalse(rng.encloses(Range.at_most(3)))
        self.assertFalse(rng.encloses(Range.all()))
コード例 #11
0
    def test_pickling(self):
        empty_rangemap = immutablerangemap({})
        ranges = (Range.closed(0, 2), Range.closed(5,
                                                   29), Range.closed(35, 39))
        values = ("foo", "bar", "meep")
        rangemap = immutablerangemap(zip(ranges, values))

        self.assertEqual(empty_rangemap,
                         pickle.loads(pickle.dumps(empty_rangemap)))
        self.assertEqual(rangemap, pickle.loads(pickle.dumps(rangemap)))

        self.assertEqual(empty_rangemap.__reduce__(),
                         (immutablerangemap, ((), )))
        self.assertEqual(rangemap.__reduce__(),
                         (immutablerangemap, (tuple(zip(ranges, values)), )))
コード例 #12
0
 def test_intersection_empty(self):
     rng = Range.closed_open(3, 3)
     self.assertEqual(rng, rng.intersection(rng))
     with self.assertRaises(ValueError):
         rng.intersection(Range.open(3, 5))
     with self.assertRaises(ValueError):
         rng.intersection(Range.closed(0, 2))
コード例 #13
0
 def test_range_enclosing_range(self) -> None:
     range_set: MutableRangeSet[int] = RangeSet.create_mutable()
     range_set.add_all(
         [Range.at_most(2),
          Range.open_closed(5, 8),
          Range.at_least(10)])
     self.assertEqual(None,
                      range_set.range_enclosing_range(Range.closed(2, 3)))
     self.assertEqual(Range.at_most(2),
                      range_set.range_enclosing_range(Range.open(-1, 0)))
     self.assertEqual(
         Range.open_closed(5, 8),
         range_set.range_enclosing_range(Range.closed_open(6, 7)),
     )
     self.assertEqual(None,
                      range_set.range_enclosing_range(Range.closed(5, 8)))
コード例 #14
0
class HorizontalAxisOfObject(Generic[_ObjectT], AxisFunction[_ObjectT]):
    _object: _ObjectT = attrib()
    _index: int = attrib(validator=in_(Range.closed(0, 1)))

    def to_concrete_axis(
        self, axes_info: Optional[AxesInfo[_ObjectT]]  # pylint:disable=unused-argument
    ) -> GeonAxis:
        if not isinstance(self._object, HasAxes):
            raise RuntimeError(
                "Can only instantiate an axis function if the object is of a "
                "concrete type (e.g. perception or situation object)"
            )
        horizontal_axes = tuple(
            axis
            for axis in self._object.axes.all_axes
            if not axis.aligned_to_gravitational
        )
        return horizontal_axes[self._index]  # pylint:disable=invalid-sequence-index

    def copy_remapping_objects(
        self, object_map: Mapping[_ObjectT, _ObjectToT]
    ) -> "HorizontalAxisOfObject[_ObjectToT]":
        return HorizontalAxisOfObject(object_map[self._object], index=self._index)

    def __repr__(self, object_map: Optional[Mapping[_ObjectT, str]] = None) -> str:
        handle = object_map[self._object] if object_map else self._object
        return f"HorizontalAxisOfObject(_object={handle}, _index={str(self._index)})"
コード例 #15
0
    def test_closed(self):
        rng = Range.closed(5, 7)
        self.check_contains(rng)
        self.assertTrue(rng.has_lower_bound())
        self.assertEqual(5, rng.lower_endpoint)
        self.assertEqual(BoundType.closed(), rng.lower_bound_type)
        self.assertTrue(rng.has_upper_bound())
        self.assertEqual(7, rng.upper_endpoint)
        self.assertEqual(BoundType.closed(), rng.upper_bound_type)
        self.assertFalse(rng.is_empty())
        self.assertEqual("[5..7]", str(rng))
        # this is legal and should raise no exception
        Range.closed(4, 4)

        with self.assertRaises(ValueError):
            Range.closed(8, 4)
コード例 #16
0
    def test_enclosed(self):
        range_map: ImmutableRangeMap[int,
                                     str] = (ImmutableRangeMap.builder().put(
                                         Range.closed(0, 2),
                                         "foo").put(Range.open_closed(6, 8),
                                                    "bar").put(
                                                        Range.open(12, 14),
                                                        "meep").build())

        self.assertEqual(
            ImmutableSet.of(["foo", "bar", "meep"]),
            range_map.get_enclosed_by(Range.closed(-1, 15)),
        )
        self.assertEqual(ImmutableSet.of(["foo"]),
                         range_map.get_enclosed_by(Range.closed(0, 6)))
        self.assertEqual(ImmutableSet.empty(),
                         range_map.get_enclosed_by(Range.closed(5, 5)))
コード例 #17
0
 def test_lookup(self):
     range_map = (ImmutableRangeMap.builder().put(Range.closed(
         0, 2), "foo").put(Range.open_closed(6, 8), "bar").build())
     self.assertEqual("foo", range_map[0])
     self.assertEqual("foo", range_map[1])
     self.assertEqual("foo", range_map[2])
     self.assertEqual(None, range_map[6])
     self.assertEqual("bar", range_map[7])
     self.assertEqual("bar", range_map[8])
     self.assertEqual(None, range_map[9])
コード例 #18
0
 def test_singleton(self):
     rng = Range.closed(4, 4)
     self.assertFalse(3 in rng)
     self.assertTrue(4 in rng)
     self.assertFalse(5 in rng)
     self.assertTrue(rng.has_lower_bound())
     self.assertEqual(4, rng.lower_endpoint)
     self.assertEqual(BoundType.closed(), rng.lower_bound_type)
     self.assertTrue(rng.has_upper_bound())
     self.assertEqual(4, rng.upper_endpoint)
     self.assertEqual(BoundType.closed(), rng.upper_bound_type)
     self.assertFalse(rng.is_empty())
     self.assertEqual("[4..4]", str(rng))
コード例 #19
0
    def test_pickling(self):
        empty_mutable_rangeset = MutableRangeSet.create_mutable()
        empty_immutable_rangeset = ImmutableRangeSet.builder().build()
        ranges = (Range.closed(0, 2), Range.closed(5,
                                                   29), Range.closed(35, 39))
        mutable_rangeset = MutableRangeSet.create_mutable().add_all(ranges)
        immutable_rangeset = ImmutableRangeSet.builder().add_all(
            ranges).build()

        self.assertEqual(empty_mutable_rangeset,
                         pickle.loads(pickle.dumps(empty_mutable_rangeset)))
        self.assertEqual(empty_immutable_rangeset,
                         pickle.loads(pickle.dumps(empty_immutable_rangeset)))
        self.assertEqual(mutable_rangeset,
                         pickle.loads(pickle.dumps(mutable_rangeset)))
        self.assertEqual(immutable_rangeset,
                         pickle.loads(pickle.dumps(immutable_rangeset)))

        self.assertEqual(empty_mutable_rangeset.__getstate__(), ())
        self.assertEqual(empty_immutable_rangeset.__getstate__(), ())

        self.assertEqual(mutable_rangeset.__getstate__(), ranges)
        self.assertEqual(immutable_rangeset.__getstate__(), ranges)
コード例 #20
0
class RgbColorPerception:
    """
    A perceived color.
    """

    red: int = attrib(validator=in_(Range.closed(0, 255)))
    green: int = attrib(validator=in_(Range.closed(0, 255)))
    blue: int = attrib(validator=in_(Range.closed(0, 255)))

    def inverse(self) -> "RgbColorPerception":
        return RgbColorPerception(255 - self.red, 255 - self.green,
                                  255 - self.blue)

    @property
    def hex(self) -> str:
        return f"#{self.red:02x}{self.green:02x}{self.blue:02x}"

    def __repr__(self) -> str:
        """
        We represent colors by hex strings because these are easy to visualize using web tools.
        Returns:

        """
        return self.hex
コード例 #21
0
    def test_intersection_de_facto_empty(self):
        rng = Range.open(3, 4)
        self.assertEqual(rng, rng.intersection(rng))
        self.assertEqual(Range.open_closed(3, 3),
                         rng.intersection(Range.at_most(3)))
        self.assertEqual(Range.closed_open(4, 4),
                         rng.intersection(Range.at_least(4)))

        with self.assertRaises(ValueError):
            rng.intersection(Range.less_than(3))
        with self.assertRaises(ValueError):
            rng.intersection(Range.greater_than(4))

        rng2 = Range.closed(3, 4)
        self.assertEqual(Range.open_closed(4, 4),
                         rng2.intersection(Range.greater_than(4)))
コード例 #22
0
    def test_intersection_singleton(self):
        rng = Range.closed(3, 3)
        self.assertEqual(rng, rng.intersection(rng))

        self.assertEqual(rng, rng.intersection(Range.at_most(4)))
        self.assertEqual(rng, rng.intersection(Range.at_most(3)))
        self.assertEqual(rng, rng.intersection(Range.at_least(3)))
        self.assertEqual(rng, rng.intersection(Range.at_least(2)))

        self.assertEqual(Range.closed_open(3, 3),
                         rng.intersection(Range.less_than(3)))
        self.assertEqual(Range.open_closed(3, 3),
                         rng.intersection(Range.greater_than(3)))

        with self.assertRaises(ValueError):
            rng.intersection(Range.at_least(4))
        with self.assertRaises(ValueError):
            rng.intersection(Range.at_most(2))
コード例 #23
0
 def test_optional_defaults(self):
     empty_params = Parameters.empty()
     default_list = [False]
     assert (empty_params.optional_arbitrary_list(  # pylint: disable=unexpected-keyword-arg
         "foo",
         default=default_list) == default_list)
     assert empty_params.optional_boolean(  # pylint: disable=unexpected-keyword-arg
         "foo", default=True)
     assert (  # pylint: disable=unexpected-keyword-arg
         empty_params.optional_floating_point("foo", default=-1.5) == -1.5)
     assert (  # pylint: disable=unexpected-keyword-arg
         empty_params.optional_integer("foo", default=-5) == -5)
     assert (  # pylint: disable=unexpected-keyword-arg
         empty_params.optional_positive_integer("foo", default=5) == 5)
     assert (  # pylint: disable=unexpected-keyword-arg
         empty_params.optional_string("foo", default="test") == "test")
     with self.assertRaises(ParameterError):
         empty_params.optional_floating_point(  # pylint: disable=unexpected-keyword-arg
             "foo",
             default=-1.5,
             valid_range=Range.closed(0.0, 10.0))
コード例 #24
0
 def test_intersect_ranges(self):
     range_set = RangeSet.create_mutable()
     range_set.add_all([
         Range.closed(2, 4),
         Range.closed(5, 7),
         Range.closed(10, 12),
         Range.closed(18, 20),
     ])
     self.assertEqual(
         range_set.ranges_overlapping(Range.closed(19, 21)),
         immutableset([Range.closed(18, 20)]),
     )
     self.assertEqual(
         range_set.ranges_overlapping(Range.closed(11, 19)),
         immutableset([Range.closed(10, 12),
                       Range.closed(18, 20)]),
     )
     self.assertEqual(range_set.ranges_overlapping(Range.closed(0, 1)),
                      immutableset())
     self.assertEqual(range_set.ranges_overlapping(Range.closed(21, 23)),
                      immutableset())
     self.assertEqual(range_set.ranges_overlapping(Range.closed(13, 15)),
                      immutableset())
     self.assertEqual(
         range_set.ranges_overlapping(Range.closed(0, 2)),
         immutableset([Range.closed(2, 4)]),
     )
     self.assertEqual(
         range_set.ranges_overlapping(Range.closed(12, 15)),
         immutableset([Range.closed(10, 12)]),
     )
     self.assertEqual(
         range_set.ranges_overlapping(Range.closed(5, 16)),
         immutableset([Range.closed(5, 7),
                       Range.closed(10, 12)]),
     )
コード例 #25
0
 def test_merges_connected_disjoint(self):
     range_set = RangeSet.create_mutable()
     range_set.add(Range.closed(1, 4))
     range_set.add(Range.open(4, 6))
     self._test_invariants(range_set)
     self.assertTrue(Range.closed_open(1, 6) in range_set.as_ranges())
コード例 #26
0
 def test_ignores_smaller_sharing_upper_bound(self):
     range_set = RangeSet.create_mutable()
     range_set.add(Range.closed(1, 6))
     range_set.add(Range.closed(3, 6))
     self._test_invariants(range_set)
     self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())
コード例 #27
0
class TestRangeSet(TestCase):
    """
    Tests for RangeSet

    Derived from Guava's TreeRangeSet tests, which were written by Louis Wasserman and Chris Povrik
    """

    MIN_BOUND = -1
    MAX_BOUND = 1
    BOUND_TYPES = [BoundType.open(), BoundType.closed()]

    QUERY_RANGES: List[Range[int]] = [Range.all()]
    for i in range(MIN_BOUND, MAX_BOUND + 1):
        QUERY_RANGES.extend([
            Range.at_most(i),
            Range.at_least(i),
            Range.less_than(i),
            Range.greater_than(i),
            Range.closed(i, i),
            Range.open_closed(i, i),
            Range.closed_open(i, i),
        ])
        for j in range(i + 1, MAX_BOUND + 1):
            QUERY_RANGES.extend([
                Range.open(i, j),
                Range.open_closed(i, j),
                Range.closed_open(i, j),
                Range.closed(i, j),
            ])

    def test_empty_enclosing(self):
        self._test_encloses(RangeSet.create_mutable())

    def test_empty_intersects(self):
        self._test_intersects(RangeSet.create_mutable())

    def test_all_single_ranges_enclosing(self):
        for query_range in TestRangeSet.QUERY_RANGES:
            self._test_encloses(RangeSet.create_mutable().add(query_range))
        # also test for the complement of empty once complements are implemented

    def test_all_pair_ranges_enclosing(self):
        for query_range_1 in TestRangeSet.QUERY_RANGES:
            for query_range_2 in TestRangeSet.QUERY_RANGES:
                self._test_encloses(RangeSet.create_mutable().add(
                    query_range_1).add(query_range_2))

    def test_intersect_ranges(self):
        range_set = RangeSet.create_mutable()
        range_set.add_all([
            Range.closed(2, 4),
            Range.closed(5, 7),
            Range.closed(10, 12),
            Range.closed(18, 20),
        ])
        self.assertEqual(
            range_set.ranges_overlapping(Range.closed(19, 21)),
            immutableset([Range.closed(18, 20)]),
        )
        self.assertEqual(
            range_set.ranges_overlapping(Range.closed(11, 19)),
            immutableset([Range.closed(10, 12),
                          Range.closed(18, 20)]),
        )
        self.assertEqual(range_set.ranges_overlapping(Range.closed(0, 1)),
                         immutableset())
        self.assertEqual(range_set.ranges_overlapping(Range.closed(21, 23)),
                         immutableset())
        self.assertEqual(range_set.ranges_overlapping(Range.closed(13, 15)),
                         immutableset())
        self.assertEqual(
            range_set.ranges_overlapping(Range.closed(0, 2)),
            immutableset([Range.closed(2, 4)]),
        )
        self.assertEqual(
            range_set.ranges_overlapping(Range.closed(12, 15)),
            immutableset([Range.closed(10, 12)]),
        )
        self.assertEqual(
            range_set.ranges_overlapping(Range.closed(5, 16)),
            immutableset([Range.closed(5, 7),
                          Range.closed(10, 12)]),
        )

    def test_merges_connected_with_overlap(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(1, 4))
        range_set.add(Range.open(2, 6))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed_open(1, 6) in range_set.as_ranges())

    def test_merges_connected_disjoint(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(1, 4))
        range_set.add(Range.open(4, 6))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed_open(1, 6) in range_set.as_ranges())

    def test_ignores_smaller_sharing_no_bound(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(1, 6))
        range_set.add(Range.open(2, 4))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())

    def test_ignores_smaller_sharing_lower_bound(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(1, 6))
        range_set.add(Range.closed(1, 4))
        self._test_invariants(range_set)
        self.assertEqual(tuple([Range.closed(1, 6)]),
                         tuple(range_set.as_ranges()))

    def test_ignores_smaller_sharing_upper_bound(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(1, 6))
        range_set.add(Range.closed(3, 6))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())

    def test_ignores_equal(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(1, 6))
        range_set.add(Range.closed(1, 6))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())

    def test_extend_same_lower_bound(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(1, 4))
        range_set.add(Range.closed(1, 6))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())

    def test_extend_same_upper_bound(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(3, 6))
        range_set.add(Range.closed(1, 6))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())

    def test_extend_both_directions(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(3, 4))
        range_set.add(Range.closed(1, 6))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())

    def test_add_empty(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed_open(3, 3))
        self._test_invariants(range_set)
        self.assertTrue(len(range_set.as_ranges()) == 0)
        self.assertTrue(range_set.is_empty())

    def test_fill_hole_exactly(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed_open(1, 3))
        range_set.add(Range.closed_open(4, 6))
        range_set.add(Range.closed_open(3, 4))
        self._test_invariants(range_set)
        self.assertTrue(Range.closed_open(1, 6) in range_set.as_ranges())

    def test_fill_hole_with_overlap(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed_open(1, 3))
        range_set.add(Range.closed_open(4, 6))
        range_set.add(Range.closed_open(2, 5))
        self._test_invariants(range_set)
        self.assertEqual(tuple([Range.closed_open(1, 6)]),
                         tuple(range_set.as_ranges()))

    def test_add_many_pairs(self):
        for a_low in range(0, 6):
            for a_high in range(0, 6):
                if a_low > a_high:
                    continue
                a_ranges = [
                    Range.closed(a_low, a_high),
                    Range.open_closed(a_low, a_high),
                    Range.closed_open(a_low, a_high),
                ]
                if a_low != a_high:
                    a_ranges.append(Range.open(a_low, a_high))

                for b_low in range(0, 6):
                    for b_high in range(0, 6):
                        if b_low > b_high:
                            continue
                        b_ranges = [
                            Range.closed(b_low, b_high),
                            Range.open_closed(b_low, b_high),
                            Range.closed_open(b_low, b_high),
                        ]
                        if b_low != b_high:
                            b_ranges.append(Range.open(b_low, b_high))
                        for a_range in a_ranges:
                            for b_range in b_ranges:
                                self._pair_test(a_range, b_range)

    def test_range_containing1(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(3, 10))
        self.assertEqual(Range.closed(3, 10), range_set.range_containing(5))
        self.assertTrue(5 in range_set)
        self.assertIsNone(range_set.range_containing(1))
        self.assertFalse(1 in range_set)

    def test_add_all(self):
        range_set = RangeSet.create_mutable()
        range_set.add(Range.closed(3, 10))
        range_set.add_all(
            [Range.open(1, 3),
             Range.closed(5, 8),
             Range.closed(9, 11)])
        self.assertEqual(tuple(range_set.as_ranges()),
                         tuple([Range.open_closed(1, 11)]))

    def test_all_single_ranges_intersecting(self):
        for query in TestRangeSet.QUERY_RANGES:
            self._test_intersects(RangeSet.create_mutable().add(query))

    def test_all_two_ranges_intersecting(self):
        for query_1 in TestRangeSet.QUERY_RANGES:
            for query_2 in TestRangeSet.QUERY_RANGES:
                self._test_intersects(
                    RangeSet.create_mutable().add(query_1).add(query_2))

    # forms the basis for corresponding tests in test_range_map
    def test_rightmost_containing_or_below(self):
        range_set = RangeSet.create_mutable().add_all((
            Range.closed(-2, -1),
            Range.closed_open(0, 2),
            # we don't do [0, 2), [2.1, 3] because they will coalesce
            # ditto for (4, 5] and (5.1, 7)
            Range.closed(2.1, 3),
            Range.open_closed(4, 5),
            Range.open(5.1, 7),
        ))

        # probe value is in the middle of a set
        # [2.1  ... *2.5* ... 3]
        self.assertEqual(Range.closed(2.1, 3.0),
                         range_set.rightmost_containing_or_below(2.5))
        # probe value is at a closed upper limit
        # [2.1 .... *3*]
        self.assertEqual(Range.closed(2.1, 3.0),
                         range_set.rightmost_containing_or_below(3.0))
        # probe value is at a closed lower limit
        # [*2.1* .... 3]
        self.assertEqual(Range.closed(2.1, 3.0),
                         range_set.rightmost_containing_or_below(2.1))
        # probe value is at an open lower limit
        # [2.1 ... 3], (*4* ... 5]
        self.assertEqual(Range.closed(2.1, 3.0),
                         range_set.rightmost_containing_or_below(4.0))
        # probe value is at an open upper limit
        # [0 ... *2.1*)
        self.assertEqual(Range.closed_open(0.0, 2.0),
                         range_set.rightmost_containing_or_below(2.0))
        # probe value falls into a gap
        # [-2, -1] ... *-0.5* ... [0, 2)
        self.assertEqual(Range.closed(-2.0, -1.0),
                         range_set.rightmost_containing_or_below(-0.5))
        # no range below
        # *-3* .... [-2,-1]
        self.assertIsNone(range_set.rightmost_containing_or_below(-3.0))
        # empty rangeset
        self.assertIsNone(RangeSet.create_mutable().add(Range.closed(
            1.0, 2.0)).rightmost_containing_or_below(0.0))
        # lowest range has open lower bound
        # (*1*,2)
        self.assertIsNone(RangeSet.create_mutable().add(Range.open(
            1.0, 2.0)).rightmost_containing_or_below(1.0))

    # forms the basis for corresponding tests in test_range_set
    def test_leftmost_containing_or_above(self):
        range_set = RangeSet.create_mutable().add_all((
            Range.closed(-2, -1),
            Range.closed_open(0, 2),
            # we don't do [0, 2), [2.1, 3] because they will coalesce
            # ditto for (4, 5] and (5.1, 7)
            Range.closed(2.1, 3),
            Range.open_closed(4, 5),
            Range.open(5.1, 7),
        ))

        # probe value is in the middle of a set
        # [2.1  ... *2.5* ... 3]
        self.assertEqual(Range.closed(2.1, 3.0),
                         range_set.leftmost_containing_or_above(2.5))
        # probe value is at a closed upper limit
        # [2.1 .... *3*]
        self.assertEqual(Range.closed(2.1, 3.0),
                         range_set.leftmost_containing_or_above(3.0))
        # probe value is at a closed lower limit
        # [*2.1* .... 3]
        self.assertEqual(Range.closed(2.1, 3.0),
                         range_set.leftmost_containing_or_above(2.1))
        # probe value is at an open lower limit
        # [2 ... 3], (*4* ... 5]
        self.assertEqual(Range.open_closed(4.0, 5.0),
                         range_set.leftmost_containing_or_above(4.0))
        # probe value is at an open upper limit
        # [0 ... *2*) [2.1, 3.0]
        self.assertEqual(Range.closed(2.1, 3.0),
                         range_set.leftmost_containing_or_above(2.0))
        # probe value falls into a gap
        # [-2, -1] ... *-0.5* ... [0, 2)
        self.assertEqual(Range.closed_open(0, 2),
                         range_set.leftmost_containing_or_above(-0.5))
        # no range above
        # (5.1 ... 7) ... *8*
        self.assertIsNone(range_set.leftmost_containing_or_above(8))
        # empty rangeset
        self.assertIsNone(RangeSet.create_mutable().add(Range.closed(
            1.0, 2.0)).leftmost_containing_or_above(3.0))
        # higher range has open upper bound
        # (1,*2*)
        self.assertIsNone(RangeSet.create_mutable().add(Range.open(
            1.0, 2.0)).leftmost_containing_or_above(2.0))

    def test_len(self):
        self.assertEqual(0, len(RangeSet.create_mutable()))
        self.assertEqual(
            1, len(RangeSet.create_mutable().add(Range.closed(1, 2))))
        self.assertEqual(
            2,
            len(RangeSet.create_mutable().add(Range.closed(1, 2)).add(
                Range.open(3, 4))),
        )

    # support methods

    def _pair_test(self, a: Range[int], b: Range[int]) -> None:
        range_set: MutableRangeSet[int] = RangeSet.create_mutable()
        range_set.add(a)
        range_set.add(b)
        if a.is_empty() and b.is_empty():
            self.assertTrue(range_set.is_empty())
            self.assertFalse(range_set.as_ranges())
        elif a.is_empty():
            self.assertTrue(b in range_set.as_ranges())
        elif b.is_empty():
            self.assertTrue(a in range_set.as_ranges())
        elif a.is_connected(b):
            self.assertEqual(tuple(range_set.as_ranges()), tuple([a.span(b)]))
        else:
            if a.lower_endpoint < b.lower_endpoint:
                self.assertEqual(tuple(range_set.as_ranges()), tuple([a, b]))
            else:
                self.assertEqual(ImmutableSet.of([a, b]),
                                 ImmutableSet.of(range_set.as_ranges()))

    def _test_encloses(self, range_set: RangeSet[int]):
        self.assertTrue(range_set.encloses_all(ImmutableSet.empty()))
        for query_range in TestRangeSet.QUERY_RANGES:
            expected_to_enclose = any(
                x.encloses(query_range) for x in range_set.as_ranges())
            self.assertEqual(expected_to_enclose,
                             range_set.encloses(query_range))
            self.assertEqual(expected_to_enclose,
                             range_set.encloses_all([query_range]))

    def _test_intersects(self, range_set: RangeSet[int]):
        for query in TestRangeSet.QUERY_RANGES:
            expect_intersects = any(
                r.is_connected(query) and not r.intersection(query).is_empty()
                for r in range_set.as_ranges())
            self.assertEqual(expect_intersects, range_set.intersects(query))

    def _test_invariants(self, range_set: RangeSet[int]):
        self.assertEqual(len(range_set.as_ranges()) == 0, range_set.is_empty())
        as_ranges: Sequence[Range[int]] = tuple(range_set.as_ranges())

        # test that connected ranges are coalesced
        for (range_1, range_2) in tile_with_pairs(as_ranges):
            self.assertFalse(range_1.is_connected(range_2))

        for rng in as_ranges:
            self.assertFalse(rng.is_empty())

        # test that the RangeSet's span is the span of all the ranges
        if as_ranges:
            self.assertEqual(Range.create_spanning(range_set.as_ranges()),
                             range_set.span)
        else:
            with self.assertRaises(ValueError):
                # pylint: disable=pointless-statement
                # noinspection PyStatementEffect
                range_set.span

    # test internal utility functions

    def test_entry_above_below(self):
        sorted_dict = SortedDict({1: 1, 3: 3, 5: 5, 7: 7, 9: 9})
        value_at_or_below_reference = (
            (0, None),
            (1, 1),
            (2, 1),
            (3, 3),
            (4, 3),
            (5, 5),
            (6, 5),
            (7, 7),
            (8, 7),
            (9, 9),
            (10, 9),
            (200, 9),
        )
        for (key, ref) in value_at_or_below_reference:
            self.assertEqual(_value_at_or_below(sorted_dict, key), ref)

        value_below_reference = (
            (0, None),
            (1, None),
            (2, 1),
            (3, 1),
            (4, 3),
            (5, 3),
            (6, 5),
            (7, 5),
            (8, 7),
            (9, 7),
            (10, 9),
            (200, 9),
        )
        for (key, ref) in value_below_reference:
            self.assertEqual(_value_below(sorted_dict, key), ref)

        value_at_or_above_reference = (
            (0, 1),
            (1, 1),
            (2, 3),
            (3, 3),
            (4, 5),
            (5, 5),
            (6, 7),
            (7, 7),
            (8, 9),
            (9, 9),
            (10, None),
            (200, None),
        )
        for (key, ref) in value_at_or_above_reference:
            self.assertEqual(_value_at_or_above(sorted_dict, key), ref)

    def test_pickling(self):
        empty_mutable_rangeset = MutableRangeSet.create_mutable()
        empty_immutable_rangeset = ImmutableRangeSet.builder().build()
        ranges = (Range.closed(0, 2), Range.closed(5,
                                                   29), Range.closed(35, 39))
        mutable_rangeset = MutableRangeSet.create_mutable().add_all(ranges)
        immutable_rangeset = ImmutableRangeSet.builder().add_all(
            ranges).build()

        self.assertEqual(empty_mutable_rangeset,
                         pickle.loads(pickle.dumps(empty_mutable_rangeset)))
        self.assertEqual(empty_immutable_rangeset,
                         pickle.loads(pickle.dumps(empty_immutable_rangeset)))
        self.assertEqual(mutable_rangeset,
                         pickle.loads(pickle.dumps(mutable_rangeset)))
        self.assertEqual(immutable_rangeset,
                         pickle.loads(pickle.dumps(immutable_rangeset)))

        self.assertEqual(empty_mutable_rangeset.__getstate__(), ())
        self.assertEqual(empty_immutable_rangeset.__getstate__(), ())

        self.assertEqual(mutable_rangeset.__getstate__(), ranges)
        self.assertEqual(immutable_rangeset.__getstate__(), ranges)
コード例 #28
0
 def test_ignores_equal(self):
     range_set = RangeSet.create_mutable()
     range_set.add(Range.closed(1, 6))
     range_set.add(Range.closed(1, 6))
     self._test_invariants(range_set)
     self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())
コード例 #29
0
 def test_extend_same_upper_bound(self):
     range_set = RangeSet.create_mutable()
     range_set.add(Range.closed(3, 6))
     range_set.add(Range.closed(1, 6))
     self._test_invariants(range_set)
     self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())
コード例 #30
0
 def test_extend_both_directions(self):
     range_set = RangeSet.create_mutable()
     range_set.add(Range.closed(3, 4))
     range_set.add(Range.closed(1, 6))
     self._test_invariants(range_set)
     self.assertTrue(Range.closed(1, 6) in range_set.as_ranges())