Repository: rikithreddy/datastructs-pylibrary

Issue:
Add custom exceptions/errors for lists module

Discussion:

Patch:
diff --git a/datastructs/arrays/SingleDimensionArray.py b/datastructs/arrays/SingleDimensionArray.py
index eca4e4e..69f94a7 100644
--- a/datastructs/arrays/SingleDimensionArray.py
+++ b/datastructs/arrays/SingleDimensionArray.py
@@ -1,14 +1,29 @@
 from ..common import Node
 
+from ..exceptions.custom import (
+                        InvalidArraySize,
+                        InvalidDataType,
+                        InvalidArrayIndex,
+                        InvalidArrayInitializerSize
+                        )
+
 class SingleDimensionArray:
 
     def _check_index(self, index):
         if index < 0 or index >= self.size:
-            raise IndexError
+            raise InvalidArrayIndex(
+                            "Expected range of index 0 to {}, Provided {}".
+                            format(self.size, index)
+                            )
 
     def _check_value(self, elem):
         if not isinstance(elem, self.elem_type):
-            raise ValueError
+            raise InvalidDataType(
+                            "Expected data object of {}, Recieved {}".format(
+                                self.elem_type,
+                                type(elem)
+                                )
+                            )
 
     def __init__(self, elem_type, size, init=[]):
         self.size = size
@@ -21,8 +36,7 @@ class SingleDimensionArray:
                     self._check_value(elem)
                     self.array[id].data = elem          
             else:
-                print("Invalid initialization size")
-                raise ValueError
+                raise InvalidArrayInitializerSize
     
     def get(self, index):
         self._check_index(index)
diff --git a/datastructs/exceptions/__init__.py b/datastructs/exceptions/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/datastructs/exceptions/custom.py b/datastructs/exceptions/custom.py
new file mode 100644
index 0000000..e700a6f
--- /dev/null
+++ b/datastructs/exceptions/custom.py
@@ -0,0 +1,31 @@
+class StackOverFlowException(Exception):
+    def __init__(self, message):
+        super().__init__(message)
+
+class StackUnderFlowException(Exception):
+    def __init__(self):
+        super().__init__("The stack is empty")
+
+class StackEmpty(Exception):
+    pass
+
+class QueueEmpty(Exception):
+    pass
+
+class LinkedListEmpty(Exception):
+    pass
+
+class InvalidArraySize(Exception):
+    pass
+
+class InvalidArrayIndex(Exception):
+    def __init__(self, message):
+        super().__init__(message)
+
+class InvalidArrayInitializerSize(Exception):
+    pass
+
+
+class InvalidDataType(Exception):
+    def __init__(self, msg):
+        super().__init__(msg)
\ No newline at end of file
diff --git a/datastructs/lists/SingleLinkList.py b/datastructs/lists/SingleLinkList.py
index 1ff2b8e..601f178 100644
--- a/datastructs/lists/SingleLinkList.py
+++ b/datastructs/lists/SingleLinkList.py
@@ -2,11 +2,21 @@ from ..common import Node
 from sys import stdout
 from copy import copy
 
+from ..exceptions.custom import (
+                        InvalidDataType,
+                        LinkedListEmpty
+                        )
+
 class SingleLinkList:
 
     def _check_value(self, elem):
         if not isinstance(elem, self.elem_type):
-            raise ValueError
+            raise InvalidDataType(
+                            "Expected data object of {}, Recieved {}".format(
+                                self.elem_type,
+                                type(elem)
+                                )
+                            )
 
     def __init__(self, elem_type, has_tail=True):
         self.head = Node()
@@ -42,15 +52,12 @@ class SingleLinkList:
         if self.head.next is not None:
             return self.head.next.data
         else:
-            # TODO: Add Error
-            print("List is empty")
-            raise IndexError
+            raise LinkedListEmpty
 
     def pop_first_element(self):
         if self.head and not self.head.next:
-            # TODO: Add error
-            print("Error List is empty")
-            raise IndexError
+            raise LinkedListEmpty
+        
         if self.has_tail and self.tail == self.head.next:
             self.tail = self.head
         node = self.head.next
@@ -90,9 +97,7 @@ class SingleLinkList:
         if not self.list_empty():
             return self.get_last_node().data
         else:
-            # TODO: Add Error
-            print("List is empty")
-            raise IndexError
+            raise LinkedListEmpty
 
     def find_element(self, data):
         '''
diff --git a/datastructs/queues/ListQueue.py b/datastructs/queues/ListQueue.py
index 89e10c2..e562e52 100644
--- a/datastructs/queues/ListQueue.py
+++ b/datastructs/queues/ListQueue.py
@@ -1,4 +1,8 @@
 from ..lists.SingleLinkList import SingleLinkList
+from ..exceptions.custom import (
+                            QueueEmpty,
+                            LinkedListEmpty
+                            )
 
 class ListQueue:
 
@@ -12,11 +16,14 @@ class ListQueue:
     
     def next_key(self):
         if self.queue_empty():
-            raise IndexError
+            raise QueueEmpty
         return self.top.next.data
     
     def enqueue(self, key):
         self.queue.add_to_back(key)
     
     def dequeue(self):
-        return self.queue.pop_first_element()
\ No newline at end of file
+        try:
+            return self.queue.pop_first_element()
+        except LinkedListEmpty:
+            raise QueueEmpty
\ No newline at end of file
diff --git a/datastructs/stacks/ListStack.py b/datastructs/stacks/ListStack.py
index 177ebc8..bcaae8d 100644
--- a/datastructs/stacks/ListStack.py
+++ b/datastructs/stacks/ListStack.py
@@ -1,4 +1,8 @@
 from ..lists.SingleLinkList import SingleLinkList
+from ..exceptions.custom import (
+                    StackUnderFlowException,
+                    LinkedListEmpty
+                    )
 
 class ListStack:
 
@@ -12,11 +16,14 @@ class ListStack:
     
     def top_elem(self):
         if self.stack_empty():
-            raise IndexError
+            raise StackUnderFlowException
         return self.top.next.data
     
     def pop(self):
-        return self.stack.pop_first_element()
-    
+        try:
+            return self.stack.pop_first_element()
+        except LinkedListEmpty:
+            raise StackUnderFlowException
+
     def push(self, elem_type):
         self.stack.add_to_front(elem_type)
\ No newline at end of file


Test patch:
diff --git a/tests/test_array.py b/tests/test_array.py
index fe18aff..0601584 100644
--- a/tests/test_array.py
+++ b/tests/test_array.py
@@ -1,29 +1,37 @@
 from datastructs.arrays.SingleDimensionArray import SingleDimensionArray as array
 import unittest
 
+from datastructs.exceptions.custom import (
+                        InvalidArraySize,
+                        InvalidDataType,
+                        InvalidArrayIndex,
+                        InvalidArrayInitializerSize
+                        )
+
+
 class TestArray(unittest.TestCase):
 
 
     def test_1d_Array(self):
-        self.assertRaises(ValueError, array, int, 1, [1,2])
+        self.assertRaises(InvalidArrayInitializerSize, array, int, 1, [1,2])
 
-        self.assertRaises(ValueError, array, int, 2, [1])
+        self.assertRaises(InvalidArrayInitializerSize, array, int, 2, [1])
 
 
-        self.assertRaises(ValueError, array, str, 1, [1])
+        self.assertRaises(InvalidDataType, array, str, 1, [1])
 
-        self.assertRaises(ValueError, array, int, 2, [1,"12"])
+        self.assertRaises(InvalidDataType, array, int, 2, [1,"12"])
 
         ar = array(int, 5, [1, 2, 3, 4, 5])
         ar.update(1, 99)
         self.assertEqual(ar.get(0), 1)
         self.assertEqual(ar.get(1), 99)
 
-        self.assertRaises(ValueError, ar.update, 1, "0")
-        self.assertRaises(IndexError, ar.update, -1, 0)
-        self.assertRaises(IndexError, ar.update, 1000, 0)
-        self.assertRaises(IndexError, ar.get, 1000)
-        self.assertRaises(IndexError, ar.get, -1)
+        self.assertRaises(InvalidDataType, ar.update, 1, "0")
+        self.assertRaises(InvalidArrayIndex, ar.update, -1, 0)
+        self.assertRaises(InvalidArrayIndex, ar.update, 1000, 0)
+        self.assertRaises(InvalidArrayIndex, ar.get, 1000)
+        self.assertRaises(InvalidArrayIndex, ar.get, -1)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_lists.py b/tests/test_lists.py
index 4692215..1cfbd9e 100644
--- a/tests/test_lists.py
+++ b/tests/test_lists.py
@@ -1,12 +1,16 @@
-from datastructs.lists.SingleLinkList import SingleLinkList
 import unittest
+from datastructs.lists.SingleLinkList import SingleLinkList
+from datastructs.exceptions.custom import (
+                                    InvalidDataType,
+                                    LinkedListEmpty
+                                    )
 
 class TestSingleLinkList(unittest.TestCase):
 
     def list_operations(self, custom_list):
-        self.assertRaises(IndexError, custom_list.pop_first_element)
-        self.assertRaises(IndexError, custom_list.get_first_element)
-        self.assertRaises(IndexError, custom_list.get_last_element)
+        self.assertRaises(LinkedListEmpty, custom_list.pop_first_element)
+        self.assertRaises(LinkedListEmpty, custom_list.get_first_element)
+        self.assertRaises(LinkedListEmpty, custom_list.get_last_element)
         self.assertTrue(custom_list.list_empty())
         custom_list.add_to_front(0)
         custom_list.add_to_back(1)
@@ -23,8 +27,8 @@ class TestSingleLinkList(unittest.TestCase):
         self.assertFalse(custom_list.has_element(0))
         self.assertTrue(custom_list.has_element(1))
 
-        self.assertRaises(ValueError, custom_list.add_to_front, "123")
-        self.assertRaises(ValueError, custom_list.add_to_back, "123")
+        self.assertRaises(InvalidDataType, custom_list.add_to_front, "123")
+        self.assertRaises(InvalidDataType, custom_list.add_to_back, "123")
 
     def test_add_remove(self):
         custom_list = SingleLinkList(int)
diff --git a/tests/test_queue.py b/tests/test_queue.py
index 1d52adc..1df34e5 100644
--- a/tests/test_queue.py
+++ b/tests/test_queue.py
@@ -1,20 +1,24 @@
-from datastructs.queues.ListQueue import ListQueue
 import unittest
+from datastructs.queues.ListQueue import ListQueue
+from datastructs.exceptions.custom import (
+                            InvalidDataType,
+                            QueueEmpty
+                            )
 
-class TestArray(unittest.TestCase):
+class TestQueue(unittest.TestCase):
 
 
     def test_list_queue(self):
         queue = ListQueue(int)
 
         self.assertTrue(queue.queue_empty())
-        self.assertRaises(IndexError, queue.dequeue)
-        self.assertRaises(IndexError, queue.next_key)
+        self.assertRaises(QueueEmpty, queue.dequeue)
+        self.assertRaises(QueueEmpty, queue.next_key)
 
         queue.enqueue(1)
         queue.enqueue(2)
         queue.enqueue(3)
-        self.assertRaises(ValueError, queue.enqueue, "4")
+        self.assertRaises(InvalidDataType, queue.enqueue, "4")
 
         self.assertEqual(queue.dequeue(), 1)
         self.assertEqual(queue.next_key(), 2)
diff --git a/tests/test_stack.py b/tests/test_stack.py
index 4b7e91f..fe0b0a6 100644
--- a/tests/test_stack.py
+++ b/tests/test_stack.py
@@ -1,5 +1,9 @@
-from datastructs.stacks.ListStack import ListStack
 import unittest
+from datastructs.stacks.ListStack import ListStack
+from datastructs.exceptions.custom import (
+                    StackUnderFlowException,
+                    InvalidDataType,
+                    ) 
 
 class TestStack(unittest.TestCase):
 
@@ -8,13 +12,14 @@ class TestStack(unittest.TestCase):
         stack = ListStack(int)
 
         self.assertTrue(stack.stack_empty())
-        self.assertRaises(IndexError, stack.pop)
-        self.assertRaises(IndexError, stack.top_elem)
+        self.assertRaises(StackUnderFlowException, stack.pop)
+        self.assertRaises(StackUnderFlowException, stack.top_elem)
 
         stack.push(1)
         stack.push(2)
         stack.push(3)
-        self.assertRaises(ValueError, stack.push, "4")
+
+        self.assertRaises(InvalidDataType, stack.push, "4")
 
         self.assertEqual(stack.pop(), 3)
         self.assertEqual(stack.top_elem(), 2)