Skip to content

Commit

Permalink
Revert "Merge pull request #142 from octoenergy/make-range-instances-…
Browse files Browse the repository at this point in the history
…immutable"

This reverts commit 955adcc, reversing
changes made to 112d79e.
  • Loading branch information
jarshwah committed Mar 12, 2024
1 parent a9ef3fe commit 8d5b4a6
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 84 deletions.
33 changes: 0 additions & 33 deletions tests/test_ranges.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,6 @@ def test_creation(self):
0, 2, boundaries=ranges.RangeBoundaries.EXCLUSIVE_INCLUSIVE
) == ranges.Range(0, 2, boundaries="(]")

def test_is_immutable(self):
r = ranges.Range(0, 2, boundaries=ranges.RangeBoundaries.EXCLUSIVE_INCLUSIVE)
with pytest.raises(AttributeError, match="Can't set attributes"):
r.start = 1

def test_additional_attributes_cant_be_created(self):
r = ranges.Range(0, 2, boundaries=ranges.RangeBoundaries.EXCLUSIVE_INCLUSIVE)
with pytest.raises(
AttributeError, match="'Range' object has no attribute 'something_else'"
):
r.something_else = 1

def test_does_not_have_instance_dictionary(self):
r = ranges.Range(0, 2, boundaries=ranges.RangeBoundaries.EXCLUSIVE_INCLUSIVE)
assert not hasattr(r, "__dict__")

@pytest.mark.parametrize(
"start,end,boundaries",
[
Expand Down Expand Up @@ -473,23 +457,6 @@ def test_rangeset_difference(
assert str(rangeset - other_rangeset) == expected_result_str


class TestHalfFiniteRange:
def test_creation_uses_expected_defaults(self):
r = ranges.HalfFiniteRange(0)
assert 0 == r.start
assert r.end is None
assert ranges.RangeBoundaries.INCLUSIVE_EXCLUSIVE == r.boundaries

def test_creation(self):
r = ranges.HalfFiniteRange(1, 2)
assert 1 == r.start
assert 2 == r.end

def test_does_not_have_instance_dictionary(self):
r = ranges.HalfFiniteRange(0, 2)
assert not hasattr(r, "__dict__")


ONE_DAY = datetime.timedelta(days=1)


Expand Down
69 changes: 18 additions & 51 deletions xocto/ranges.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import operator
from typing import (
Any,
Callable,
Generic,
Iterable,
Iterator,
Expand Down Expand Up @@ -144,23 +143,15 @@ class Range(Generic[T]):
None
"""

__slots__ = (
__slots__ = [
"start",
"end",
"boundaries",
"_is_left_exclusive",
"_is_left_inclusive",
"_is_right_exclusive",
"_is_right_inclusive",
)

start: Optional[T]
end: Optional[T]
boundaries: RangeBoundaries
_is_left_exclusive: bool
_is_left_inclusive: bool
_is_right_exclusive: bool
_is_right_inclusive: bool
]

def __init__(
self,
Expand All @@ -174,45 +165,39 @@ def __init__(
Also set some convenience properties for internal use.
"""
self.start = start
self.end = end
# Make sure that we are dealing with an enum in case the class was constructed with the
# string representation of the boundaries
range_boundaries: RangeBoundaries = RangeBoundaries(boundaries)
self.boundaries: RangeBoundaries = RangeBoundaries(boundaries)

_is_left_exclusive = range_boundaries in [
self._is_left_exclusive = self.boundaries in [
RangeBoundaries.EXCLUSIVE_EXCLUSIVE,
RangeBoundaries.EXCLUSIVE_INCLUSIVE,
]
_is_right_exclusive = range_boundaries in [
self._is_right_exclusive = self.boundaries in [
RangeBoundaries.EXCLUSIVE_EXCLUSIVE,
RangeBoundaries.INCLUSIVE_EXCLUSIVE,
]
_is_left_inclusive = not _is_left_exclusive
_is_right_inclusive = not _is_right_exclusive
self._is_left_inclusive = not self._is_left_exclusive
self._is_right_inclusive = not self._is_right_exclusive

if start is None:
if _is_left_inclusive:
if self.start is None:
if self._is_left_inclusive:
raise ValueError("Range with unbounded start must be left-exclusive")
if end is None:
if _is_right_inclusive:
if self.end is None:
if self._is_right_inclusive:
raise ValueError("Range with unbounded end must be right-exclusive")
elif start is not None:
check_op: Callable[[Any, Any], bool] = {
elif self.start is not None:
check_op = {
RangeBoundaries.EXCLUSIVE_EXCLUSIVE: operator.lt,
RangeBoundaries.EXCLUSIVE_INCLUSIVE: operator.lt,
RangeBoundaries.INCLUSIVE_EXCLUSIVE: operator.lt,
RangeBoundaries.INCLUSIVE_INCLUSIVE: operator.le,
}[range_boundaries]
if not check_op(start, end):
}[self.boundaries]
if not check_op(self.start, self.end):
raise ValueError("Invalid boundaries for range")

object.__setattr__(self, "start", start)
object.__setattr__(self, "end", end)
object.__setattr__(self, "boundaries", range_boundaries)
object.__setattr__(self, "_is_left_exclusive", _is_left_exclusive)
object.__setattr__(self, "_is_left_inclusive", _is_left_inclusive)
object.__setattr__(self, "_is_right_exclusive", _is_right_exclusive)
object.__setattr__(self, "_is_right_inclusive", _is_right_inclusive)

@classmethod
def continuum(cls) -> Range[T]:
"""
Expand All @@ -236,12 +221,6 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return f"<Range: {str(self)}>"

def __setattr__(self, name: str, value: Any) -> None:
if name in type(self).__slots__:
raise AttributeError("Can't set attributes")
else:
super().__setattr__(name, value)

def __hash__(self) -> int:
return hash((self.start, self.end, self.boundaries))

Expand Down Expand Up @@ -469,9 +448,6 @@ class FiniteRange(Range[T]):
and then skip checking if the endpoints are None.
"""

__slots__ = ()

# Redefine types in base class
start: T
end: T

Expand All @@ -497,13 +473,8 @@ class HalfFiniteRange(Range[T]):
HalfFiniteRange.
"""

__slots__ = ()

# Redefine types in base class
start: T

def __init__(self, start: T, end: Optional[T] = None):
super().__init__(start, end, boundaries=RangeBoundaries.INCLUSIVE_EXCLUSIVE)
boundaries = RangeBoundaries.INCLUSIVE_EXCLUSIVE

def intersection(self, other: Range[T]) -> Optional["HalfFiniteRange[T]"]:
"""
Expand Down Expand Up @@ -809,8 +780,6 @@ class FiniteDatetimeRange(FiniteRange[datetime.datetime]):
of time.
"""

__slots__ = ()

def __init__(self, start: datetime.datetime, end: datetime.datetime):
"""
Force the boundaries of the range to be [).
Expand Down Expand Up @@ -856,8 +825,6 @@ class FiniteDateRange(FiniteRange[datetime.date]):
of whole days.
"""

__slots__ = ()

def __init__(self, start: datetime.date, end: datetime.date):
"""
Force the boundaries of the range to be [].
Expand Down

0 comments on commit 8d5b4a6

Please sign in to comment.