Skip to content

Commit

Permalink
Add factory methods
Browse files Browse the repository at this point in the history
  • Loading branch information
kvesteri committed Feb 27, 2016
1 parent 06f7a70 commit 216a7b5
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 19 deletions.
8 changes: 8 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ Changelog
Here you can see the full list of changes between each intervals release.


0.7.0 (2016-02-27)
^^^^^^^^^^^^^^^^^^

- Added canonicalize to main module import
- Added factory methods for easier interval initialization ``open``, ``closed``, ``open_closed``, ``closed_open``, ``greater_than``, ``at_least``, ``less_than``, ``at_most`` and ``all``
- Renamed ``open`` and ``closed`` properties to ``is_open`` and ``is_closed``


0.6.0 (2016-01-28)
^^^^^^^^^^^^^^^^^^

Expand Down
49 changes: 41 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,42 @@ Interval initialization
-----------------------


Intervals can be initialized using the class constructor or ``from_string``
class method. The first argument of class constructor should define the bounds
of the interval.
Intervals can be initialized using the class constructor, various factory methods or ``from_string`` class method. The recommended way is to use the factory methods.

========= =================== ================
Notation Definition Factory method
========= =================== ================
(a..b) {x | a < x < b} open
[a..b] {x | a <= x <= b} closed
(a..b] {x | a < x <= b} open_closed
[a..b) {x | a <= x < b} closed_open
(a..+∞) {x | x > a} greater_than
[a..+∞) {x | x >= a} at_least
(-∞..b) {x | x < b} less_than
(-∞..b] {x | x <= b} at_most
(-∞..+∞) {x} all
========= =================== ================


.. code-block:: python
>>> from intervals import IntInterval
>>> interval = IntInterval.open_closed(1, 5)
>>> interval.lower
1
>>> interval.upper
5
>>> interval.upper_inc
True
>>> interval = IntInterval.all()
>>> interval.lower
-inf
>>> interval.upper
inf
The first argument of class constructor should define the bounds of the interval.


.. code-block:: python
Expand Down Expand Up @@ -135,7 +168,7 @@ Intervals can be either open, half-open or closed. Properties ``lower_inc`` and
.. code-block:: python
>>> interval = IntInterval((1, 4))
>>> interval.open
>>> interval.is_open
True
>>> interval.lower_inc
False
Expand All @@ -149,7 +182,7 @@ Intervals can be either open, half-open or closed. Properties ``lower_inc`` and
>>> from intervals import Interval
>>> interval = IntInterval.from_string('[1, 4)')
>>> interval.open
>>> interval.is_open
False
>>> interval.lower_inc
True
Expand All @@ -161,7 +194,7 @@ Intervals can be either open, half-open or closed. Properties ``lower_inc`` and
.. code-block:: python
>>> interval = IntInterval.from_string('[1, 4]')
>>> interval.closed
>>> interval.is_closed
True
>>> interval.lower_inc
True
Expand All @@ -179,8 +212,8 @@ Unbounded intervals are intervals where either one of the bounds is infinite.
>>> from infinity import inf
>>> from intervals import IntInterval
>>> interval = IntInterval([1, inf])
>>> interval = IntInterval([-inf, inf])
>>> interval = IntInterval.closed_open(1, inf)
>>> interval = IntInterval.open(-inf, inf)
Interval types
--------------
Expand Down
4 changes: 3 additions & 1 deletion intervals/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from .exc import IntervalException, RangeBoundsException
from .interval import (
AbstractInterval,
canonicalize,
CharacterInterval,
DateInterval,
DateTimeInterval,
Expand All @@ -16,6 +17,7 @@
__all__ = (
'AbstractInterval',
'CharacterInterval',
'canonicalize',
'DateInterval',
'DateTimeInterval',
'DecimalInterval',
Expand All @@ -29,4 +31,4 @@
)


__version__ = '0.6.0'
__version__ = '0.7.0'
93 changes: 87 additions & 6 deletions intervals/interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,87 @@ def __init__(
self.upper
)

@classmethod
def open(cls, lower_bound, upper_bound, **kwargs):
return cls(
[lower_bound, upper_bound],
lower_inc=False,
upper_inc=False,
**kwargs
)

@classmethod
def closed(cls, lower_bound, upper_bound, **kwargs):
return cls(
[lower_bound, upper_bound],
lower_inc=True,
upper_inc=True,
**kwargs
)

@classmethod
def open_closed(cls, lower_bound, upper_bound, **kwargs):
return cls(
[lower_bound, upper_bound],
lower_inc=False,
upper_inc=True,
**kwargs
)

@classmethod
def closed_open(cls, lower_bound, upper_bound, **kwargs):
return cls(
[lower_bound, upper_bound],
lower_inc=True,
upper_inc=False,
**kwargs
)

@classmethod
def greater_than(cls, lower_bound, **kwargs):
return cls(
[lower_bound, inf],
lower_inc=False,
upper_inc=False,
**kwargs
)

@classmethod
def at_least(cls, lower_bound, **kwargs):
return cls(
[lower_bound, inf],
lower_inc=True,
upper_inc=False,
**kwargs
)

@classmethod
def less_than(cls, upper_bound, **kwargs):
return cls(
[-inf, upper_bound],
lower_inc=False,
upper_inc=False,
**kwargs
)

@classmethod
def at_most(cls, upper_bound, **kwargs):
return cls(
[-inf, upper_bound],
lower_inc=False,
upper_inc=True,
**kwargs
)

@classmethod
def all(cls, **kwargs):
return cls(
[-inf, inf],
lower_inc=False,
upper_inc=False,
**kwargs
)

@classmethod
def from_string(cls, bounds_string):
return cls(
Expand Down Expand Up @@ -238,36 +319,36 @@ def round_value_by_step(self, value):
return value

@property
def open(self):
def is_open(self):
"""
Return whether or not this object is an open interval.
Examples::
>>> range = Interval.from_string('(23, 45)')
>>> range.open
>>> range.is_open
True
>>> range = Interval.from_string('[23, 45]')
>>> range.open
>>> range.is_open
False
"""
return not self.lower_inc and not self.upper_inc

@property
def closed(self):
def is_closed(self):
"""
Return whether or not this object is a closed interval.
Examples::
>>> range = Interval.from_string('(23, 45)')
>>> range.closed
>>> range.is_closed
False
>>> range = Interval.from_string('[23, 45]')
>>> range.closed
>>> range.is_closed
True
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/interval/test_canonicalize.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from datetime import date

from intervals.interval import canonicalize, DateInterval, IntInterval
from intervals import canonicalize, DateInterval, IntInterval


def test_canonicalize_integer_intervals():
Expand Down
75 changes: 75 additions & 0 deletions tests/interval/test_factory_methods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from infinity import inf

from intervals import IntInterval


class TestFactoryMethods(object):
def test_open(self):
interval = IntInterval.open(12, 14, step=2)
assert interval.lower == 12
assert interval.upper == 14
assert interval.is_open
assert interval.step == 2

def test_closed(self):
interval = IntInterval.closed(10, 11, step=2)
assert interval.lower == 10
assert interval.upper == 12
assert interval.is_closed
assert interval.step == 2

def test_open_closed(self):
interval = IntInterval.open_closed(10, 14, step=2)
assert interval.lower == 10
assert interval.upper == 14
assert not interval.lower_inc
assert interval.upper_inc
assert interval.step == 2

def test_closed_open(self):
interval = IntInterval.closed_open(10, 14, step=2)
assert interval.lower == 10
assert interval.upper == 14
assert interval.lower_inc
assert not interval.upper_inc
assert interval.step == 2

def test_greater_than(self):
interval = IntInterval.greater_than(10, step=2)
assert interval.lower == 10
assert interval.upper == inf
assert not interval.lower_inc
assert not interval.upper_inc
assert interval.step == 2

def test_at_least(self):
interval = IntInterval.at_least(10, step=2)
assert interval.lower == 10
assert interval.upper == inf
assert interval.lower_inc
assert not interval.upper_inc
assert interval.step == 2

def test_less_than(self):
interval = IntInterval.less_than(10, step=2)
assert interval.lower == -inf
assert interval.upper == 10
assert not interval.lower_inc
assert not interval.upper_inc
assert interval.step == 2

def test_at_most(self):
interval = IntInterval.at_most(10, step=2)
assert interval.lower == -inf
assert interval.upper == 10
assert not interval.lower_inc
assert interval.upper_inc
assert interval.step == 2

def test_all(self):
interval = IntInterval.all(step=2)
assert interval.lower == -inf
assert interval.upper == inf
assert not interval.lower_inc
assert not interval.upper_inc
assert interval.step == 2
6 changes: 3 additions & 3 deletions tests/interval/test_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def test_centre(self, number_range, centre):
(IntInterval.from_string('[4, 5]'), False)
)
)
def test_open(self, interval, is_open):
assert interval.open == is_open
def test_is_open(self, interval, is_open):
assert interval.is_open == is_open

@mark.parametrize(
('interval', 'is_closed'),
Expand All @@ -79,7 +79,7 @@ def test_open(self, interval, is_open):
)
)
def test_closed(self, interval, is_closed):
assert interval.closed == is_closed
assert interval.is_closed == is_closed

@mark.parametrize(
('interval', 'empty'),
Expand Down

0 comments on commit 216a7b5

Please sign in to comment.