Skip to content

Commit

Permalink
Add from_string constructor.
Browse files Browse the repository at this point in the history
  • Loading branch information
salt-die committed Nov 26, 2023
1 parent f7ec25b commit 845be63
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
39 changes: 37 additions & 2 deletions src/mind_the_gaps/gaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ class Gaps[SupportsLessThan]:
"""
A set of mutually exclusive continuous intervals.
Gaps can be created from list of endpoints or from a list of values that support less-than.
If created from a list of values, they'll be converted to endpoints with closed boundaries.
Gaps can be created from list of endpoints and values that support less-than. Values will
be converted to endpoints with closed boundaries.
"""

endpoints: list[SupportsLessThan | Endpoint[SupportsLessThan]] = field(
Expand All @@ -180,6 +180,41 @@ def __post_init__(self):
):
raise GapsNotSorted("Intervals overlap or are unsorted.")

@classmethod
def from_string(cls, gaps: str) -> Self:
"""
Create gaps from a string.
Values can only be int or float. Uses standard interval notation, i.e., `"{(-inf, 1], [2, 3)}"`.
"""
if gaps[0] != "{" or gaps[-1] != "}":
raise ValueError(
"Gap string must start and end with curly braces ('{', '}')."
)

endpoints = gaps[1:-1].replace(" ", "").split(",")
if len(endpoints) == 1:
return cls([])

for i, endpoint in enumerate(endpoints):
if endpoint.startswith(("(", "[")):
boundary = endpoint[0]
value = endpoint[1:]
elif endpoint.endswith((")", "]")):
boundary = endpoint[-1]
value = endpoint[:-1]
else:
raise ValueError(f"Invalid endpoint ({endpoint!r}).")

try:
value = int(value)
except ValueError:
value = float(value)

endpoints[i] = Endpoint(value, boundary)

return cls(endpoints)

def __invert__(self) -> Self:
return self ^ Gaps(
[Endpoint(NegativeInfinity(), "("), Endpoint(PositiveInfinity(), ")")]
Expand Down
25 changes: 25 additions & 0 deletions tests/test_from_string.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from mind_the_gaps import Endpoint, Gaps


def test_from_string_closed():
assert Gaps([0, 1, 2, 3]) == Gaps.from_string("{[0, 1], [2, 3]}")


def test_from_string_open():
assert Gaps(
[Endpoint(0, "("), Endpoint(1, ")"), Endpoint(2, "("), Endpoint(3, ")")]
) == Gaps.from_string("{(0, 1), (2, 3)}")


def test_from_string_half_open():
assert Gaps(
[Endpoint(-float("inf"), "("), 0, 1, Endpoint(2, ")")]
) == Gaps.from_string("{(-inf, 0], [1, 2)}")


def test_from_string_singleton():
assert Gaps([0, 0]) == Gaps.from_string("{[0, 0]}")


def test_from_string_empty():
assert Gaps() == Gaps.from_string("{}")

0 comments on commit 845be63

Please sign in to comment.