Repository: kvesteri/intervals

Issue:
length should return the actual length for discrete intervals
``IntInterval.from_string('[0, 2)').length`` should be `1` not `2`

Discussion:

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index ab8d128..41c7cdc 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,6 +4,12 @@ Changelog
 Here you can see the full list of changes between each intervals release.
 
 
+0.9.1 (2020-12-31)
+^^^^^^^^^^^^^^^^^^
+
+- Fixed discrete interval length (#53)
+
+
 0.9.0 (2020-07-16)
 ^^^^^^^^^^^^^^^^^^
 
diff --git a/intervals/__init__.py b/intervals/__init__.py
index 1636366..32d7508 100644
--- a/intervals/__init__.py
+++ b/intervals/__init__.py
@@ -32,4 +32,4 @@ __all__ = (
 )
 
 
-__version__ = '0.9.0'
+__version__ = '0.9.1'
diff --git a/intervals/interval.py b/intervals/interval.py
index 81bb4b9..9d27a28 100644
--- a/intervals/interval.py
+++ b/intervals/interval.py
@@ -456,6 +456,11 @@ class AbstractInterval(object):
 
     @property
     def length(self):
+        if self.discrete:
+            if not self:
+                return 0
+            if not self.lower_inc or not self.upper_inc:
+                return canonicalize(self, lower_inc=True, upper_inc=True).length
         return abs(self.upper - self.lower)
 
     @property


Test patch:
diff --git a/tests/interval/test_properties.py b/tests/interval/test_properties.py
index d70a8e8..083c9a4 100644
--- a/tests/interval/test_properties.py
+++ b/tests/interval/test_properties.py
@@ -15,16 +15,20 @@ from intervals import (
 
 class TestIntervalProperties(object):
     @mark.parametrize(
-        ('number_range', 'length'),
+        ('interval', 'length'),
         (
-            ([1, 4], 3),
-            ([-1, 1], 2),
-            ((-inf, inf), inf),
-            ((1, inf), inf),
+            (IntInterval([1, 4]), 3),
+            (IntInterval([-1, 1]), 2),
+            (IntInterval([-inf, inf]), inf),
+            (IntInterval([1, inf]), inf),
+            (IntInterval.from_string('(0, 3)'), 1),
+            (IntInterval.from_string('[0, 3)'), 2),
+            (IntInterval.from_string('(0, 2)'), 0),
+            (IntInterval.from_string('(0, 1)'), 0)
         )
     )
-    def test_length(self, number_range, length):
-        assert IntInterval(number_range).length == length
+    def test_length(self, interval, length):
+        assert interval.length == length
 
     @mark.parametrize(
         ('number_range', 'radius'),