def test_not_empty_doubly_node(helper): val = helper.get_value() node = DoublyNode(val) assert node.get_data() == val assert node.get_next() is None assert node.get_prev() is None node.set_next(None) node.set_prev(None) with pytest.raises(ValueError): DoublyNode(None) with pytest.raises(ValueError): node.set_data(None) with pytest.raises(ValueError): node.set_next(Node(None)) with pytest.raises(ValueError): node.set_prev(Node(None)) node.set_next(DoublyNode(helper.get_value())) # do nothing node.set_prev(DoublyNode(helper.get_value())) # do nothing # Given value: has __iter__ attribute lst = helper.get_list() node = DoublyNode(lst) assert node.get_data() == lst assert node.get_next() is None assert node.get_prev() is None node.set_next(DoublyNode(helper.get_string())) node.set_prev(DoublyNode(helper.get_string())) # Given value: LinkedList() dl = LinkedList(helper.get_list()) with pytest.raises(TypeError): DoublyNode(dl) # Given value: LinkedList() dl = DoublyLinkedList(helper.get_list()) with pytest.raises(TypeError): DoublyNode(dl)
def test_creating_circular_linked_list_from_iterable(helper): # Using from_iterable (small length) lst = helper.get_list() cll = CircularLinkedList(lst) assert cll._head.get_data() == lst[0] assert len(cll) == cll._length == len(lst) assert cll.to_list() == [item for item in cll] == lst # Using from_iterable (has None) with pytest.raises(ValueError): CircularLinkedList([1, 2, None, 3]) with pytest.raises(TypeError): CircularLinkedList().add_end(LinkedList()) with pytest.raises(TypeError): CircularLinkedList().add_front(DoublyLinkedList()) with pytest.raises(TypeError): CircularLinkedList().add_front(CircularLinkedList()) # Using from_iterable (big length) lst = helper.get_list(length=10000) cll = CircularLinkedList(lst) assert cll._head.get_data() == lst[0] assert len(cll) == cll._length == len(lst) assert cll.to_list() == [item for item in cll] == lst for _ in range(100): # check random indices idx = helper.get_pos_int(b=10000 - 1) assert cll[idx] == lst[idx] # Using Linked List lst = helper.get_list() tmp_cll = CircularLinkedList(lst) cll = CircularLinkedList(tmp_cll) # assert cll == tmp_cll assert len(cll) == cll._length == len(lst) assert cll.to_list() == [item for item in cll] == lst
def __init__(self, max_capacity=float("inf")): """ Creates a `Queue()` object!! Parameters ---------- max_capacity: int It's a positive integer representing the maximum number of elements a `Queue()` should contain (Default: inf). Raises ------ TypeError: If the type of `max_capacity` isn't `int` or `float`. ValueError: If the given value of `max_capacity` is less than zero. Example ------- >>> q = Queue() >>> type(q) <class 'extra.lists.queue.Queue'> >>> q._max_capacity inf You can define the maximum capacity for your own instance: >>> q = Queue(10) >>> q._max_capacity 10 Note ---- If you passed a `float` number as the maximum capacity, then the value that get assigned is the rounding of that number: >>> q = Queue(10.6) >>> q._max_capacity 11 """ if type(max_capacity) not in {int, float}: raise TypeError( f"Max Capacity of `{self.__name__}` has to be a number!!") elif max_capacity < 0: raise ValueError( f"Max capacity of `{self.__name__}` has to be >= 0") self._container = DoublyLinkedList() self._max_capacity = (round(max_capacity) if max_capacity != float("inf") else max_capacity)
def test_split(helper): lst = helper.get_list(length=100) dl = DoublyLinkedList(lst) for i in range(len(lst)): # test left list left_list, right_list = dl.split(i) assert isinstance(left_list, DoublyLinkedList) assert left_list.to_list() == lst[:i] assert left_list.copy().to_list() == lst[:i] assert left_list.reverse().to_list() == lst[:i][::-1] # test right list assert isinstance(right_list, DoublyLinkedList) assert right_list.to_list() == lst[i:] assert right_list.copy().to_list() == lst[i:] assert right_list.reverse().to_list() == lst[i:][::-1] dl.add_front(0) dl.add_end("apple") assert dl._length == len(dl) == len(lst) + 2 assert dl.to_list() == [0] + lst + ["apple"]
class Queue(Extra): """ A queue is a close cousin of the stack, as a queue is a collection of objects that are inserted and removed according to the first-in, first-out (FIFO) principle. That is, elements can be inserted at any time, but only the element that has been in the queue the longest can be next removed. We usually say that elements enter a queue at the back and are removed from the front. """ __name__ = "extra.Queue()" def __init__(self, max_capacity=float("inf")): """ Creates a `Queue()` object!! Parameters ---------- max_capacity: int It's a positive integer representing the maximum number of elements a `Queue()` should contain (Default: inf). Raises ------ TypeError: If the type of `max_capacity` isn't `int` or `float`. ValueError: If the given value of `max_capacity` is less than zero. Example ------- >>> q = Queue() >>> type(q) <class 'extra.lists.queue.Queue'> >>> q._max_capacity inf You can define the maximum capacity for your own instance: >>> q = Queue(10) >>> q._max_capacity 10 Note ---- If you passed a `float` number as the maximum capacity, then the value that get assigned is the rounding of that number: >>> q = Queue(10.6) >>> q._max_capacity 11 """ if type(max_capacity) not in {int, float}: raise TypeError( f"Max Capacity of `{self.__name__}` has to be a number!!") elif max_capacity < 0: raise ValueError( f"Max capacity of `{self.__name__}` has to be >= 0") self._container = DoublyLinkedList() self._max_capacity = (round(max_capacity) if max_capacity != float("inf") else max_capacity) # ============================= PRINT ============================== def _print_queue(self, direction_char=" "): """ Represents the `Queue()` instance as a string. Parameters ---------- direction_char: str A character that shows the direction when needed. A space character shows that there's no direction. (Default: ' ') Returns ------- str: A string representing the content of the `Queue()` instance. Example ------- >>> q = Queue() >>> q.enqueue(10) >>> print(q._print_queue()) ─┬────┬─ │ 10 │ ─┴────┴─ >>> print(q._print_queue('x')) ─┬────┬─ x│ 10 │x ─┴────┴─ >>> print(q._print_queue('⟶')) ─┬────┬─ ⟶│ 10 │⟶ ─┴────┴─ """ top_border = "─┬" middle_border = direction_char + "│" down_border = "─┴" curr_node = self._container._head while curr_node is not None: # NOTE: +2 for a space before & after `curr_node` width = len(curr_node._represent()) + 2 top_border += ("─" * width) + "┬" middle_border += f" {curr_node._represent()} │" down_border += ("─" * width) + "┴" curr_node = curr_node.get_next() # add extension if not self.is_empty(): top_border += "─" middle_border += direction_char down_border += "─" return "{}\n{}\n{}".format(top_border, middle_border, down_border) def __repr__(self): """ Represents the `Queue()` instance as a string. Returns ------- str: The string-representation of the `Queue()` instance. Example ------- >>> q = Queue() >>> q.enqueue(10) >>> q.enqueue(20) >>> q ─┬────┬────┬─ ⟶│ 20 │ 10 │⟶ ─┴────┴────┴─ """ return self._print_queue(direction_char="⟶") # ============================= LENGTH ============================== def __len__(self): """ Gets the length of the `Queue()` instance in constant time. Returns ------- int: The length of the `Queue()` instance. By Length, I mean the number of nodes of in the instance. Examples -------- >>> q = Queue() >>> len(q) 0 >>> q.enqueue(1) >>> q.enqueue(2) >>> q.enqueue(3) >>> len(q) 3 """ return len(self._container) def is_empty(self): """ Checks if `Queue()` instance is empty or not in constant time. Returns ------- bool: A boolean flag showing if the `Queue()` instance is empty or not. `True` shows that this instance is empty and `False` shows it's not empty. Example -------- >>> q = Queue() >>> q.is_empty() True >>> q.enqueue(5) >>> q.is_empty() False """ return self._container.is_empty() def is_full(self): """ Checks if `Queue()` instance is at full-capacity in constant time. Returns ------- bool: A boolean flag showing if the `Queue()` instance is full or not. `True` shows that this instance is full and `False` shows it's not full. Example -------- >>> q = Queue(max_capacity=2) >>> q.is_full() False >>> q.enqueue(5) >>> q.is_full() False >>> q.enqueue(10) >>> q.is_full() True """ return len(self) == self._max_capacity # ============================= ENQUEUE ============================== def _enqueue(self, item): """ Inserts the given `item` to end of the `Queue()`, it does that in constant time. Parameters ---------- item: object The python object to be pushed to the `Queue()`. Raises ------ UserWarning: If the `Queue()` instance was full!! By "full", I mean the number of items in the `Queue()` equals to the assigned maximum capacity. AssertionError: If the given `item` is `None` Example ------- >>> q = Queue(max_capacity=2) >>> q ─┬ ⟶│ ─┴ >>> q._enqueue(1) >>> q._enqueue(2) >>> q ─┬───┬───┬─ ⟶│ 2 │ 1 │⟶ ─┴───┴───┴─ >>> q._enqueue(3) UserWarning: Enqueuing to a full `extra.Queue()` could lead to \ missing values!! >>> q ─┬───┬───┬─ ⟶│ 3 │ 2 │⟶ ─┴───┴───┴─ """ assert item is not None if self.is_full(): warnings.warn( f"Enqueuing to a full `{self.__name__}` " + "could lead to missing values!!", UserWarning, ) self._container.remove_end() if self._max_capacity > 0: self._container._insert(0, item) def enqueue(self, item): """ Inserts the given `item` to end of the `Queue()`, it does that in constant time. Parameters ---------- item: object The python object to be pushed to the `Queue()`. Raises ------ UserWarning: If the Queue() instance was full!! By "full", I mean the number of items in the Queue() equals to the assigned maximum capacity. ValueError: If the given `item` is `None`. TypeError: If the given `item` is an instance of `Extra`. Example ------- >>> q = Queue(max_capacity=2) >>> q ─┬ ⟶│ ─┴ >>> q.enqueue(1) >>> q.enqueue(2) >>> q ─┬───┬───┬─ ⟶│ 2 │ 1 │⟶ ─┴───┴───┴─ >>> q.enqueue(3) UserWarning: Enqueuing to a full `extra.Queue()` could lead to \ missing values!! >>> q ─┬───┬───┬─ ⟶│ 3 │ 2 │⟶ ─┴───┴───┴─ """ super()._validate_item(item) self._enqueue(item) # ============================= TOP ============================== def top(self): """ Returns the first item inserted to the `Queue()` instance in constant time. Returns ------- object: The `Queue()` instance's first inserted item. Raises ------ IndexError: If the `Queue()` instance is empty!! Example ------- >>> q = Queue() >>> q.top() IndexError: Can't retrieve from an empty `extra.Queue()`!! >>> q.enqueue(10) >>> q.enqueue(20) >>> q ─┬────┬────┬─ ⟶│ 20 │ 10 │⟶ ─┴────┴────┴─ >>> q.top() 10 """ if self.is_empty(): raise IndexError( f"Can't retrieve from an empty `{self.__name__}`!!") return self._container._tail.get_data() # ============================= DEQUEUE ============================== def dequeue(self): """ Pops the first inserted item from the `Queue()` in constant time. Returns ------- object: The `Queue()` instance's first item. Raises ------ UserWarning: If the `Queue()` instance is empty!! Example ------- >>> q = Queue() >>> q.dequeue() UserWarning: Dequeuing from empty `extra.Queue()`!! >>> q.enqueue(10) >>> q.enqueue(20) >>> q ─┬────┬────┬─ ⟶│ 20 │ 10 │⟶ ─┴────┴────┴─ >>> q.dequeue() 10 >>> q ─┬────┬─ ⟶│ 20 │⟶ ─┴────┴─ """ if self.is_empty(): warnings.warn(f"Dequeuing from an empty `{self.__name__}`!!", UserWarning) return else: tail_value = self._container._tail.get_data() self._container.remove_end() return tail_value def clear(self): """ Removes all objects within the `Queue()` instance in constant time. Example ------- >>> q = Queue() >>> q.enqueue(1) >>> q.enqueue(2) >>> q.enqueue(3) >>> q ─┬───┬───┬───┬─ ⟶│ 3 │ 2 │ 1 │⟶ ─┴───┴───┴───┴─ >>> len(q) 3 >>> q.clear() >>> q ─┬ ⟶│ ─┴ >>> len(q) 0 Note ---- When you clear the `Queue()` instance, the `max_capacity` of the cleared instance remains the same as the one before. """ self.__init__(max_capacity=self._max_capacity)
def test_creating_doubly_linked_list_from_iterable(helper): # Using from_iterable (small length) lst = helper.get_list() dl = DoublyLinkedList(lst) assert dl._head.get_data() == lst[0] assert dl._tail.get_data() == lst[-1] assert len(dl) == dl._length == len(lst) assert dl.to_list() == [item for item in dl] == lst # Using from_iterable (has None) with pytest.raises(ValueError): DoublyLinkedList([1, 2, None, 3]) with pytest.raises(TypeError): DoublyLinkedList().add_end(LinkedList()) with pytest.raises(TypeError): DoublyLinkedList().add_front(DoublyLinkedList()) # Using from_iterable (big length) lst = helper.get_list(length=10000) dl = DoublyLinkedList(lst) assert dl._head.get_data() == lst[0] assert dl._tail.get_data() == lst[-1] assert len(dl) == dl._length == len(lst) assert dl.to_list() == [item for item in dl] == lst for _ in range(100): # check random indices idx = helper.get_pos_int(b=10000 - 1) assert dl[idx] == lst[idx] # Using Linked List lst = helper.get_list() tmp_dl = DoublyLinkedList(lst) dl = DoublyLinkedList(tmp_dl) assert dl == tmp_dl assert len(dl) == dl._length == len(lst) assert dl.to_list() == [item for item in dl] == lst
def test_rotate(): # rotate when inplace = False dl = DoublyLinkedList([1, 2, 3, 4, 5, 6]) rotated = dl.rotate_right(1, inplace=False) assert isinstance(rotated._head, DoublyNode) assert isinstance(rotated._tail, DoublyNode) assert rotated.to_list() == [6, 1, 2, 3, 4, 5] assert rotated._head.get_data() == 6 assert rotated._head.get_prev() is None assert rotated._tail.get_data() == 5 assert rotated._tail.get_next() is None assert rotated[4] == 4 rotated = dl.rotate_left(3, inplace=False) assert isinstance(rotated._head, DoublyNode) assert isinstance(rotated._tail, DoublyNode) assert rotated.to_list() == [4, 5, 6, 1, 2, 3] assert rotated._head.get_data() == 4 assert rotated._head.get_prev() is None assert rotated._tail.get_data() == 3 assert rotated._tail.get_next() is None assert rotated[-2] == 2 assert dl.to_list() == [1, 2, 3, 4, 5, 6] # rotate when inplace = True dl.rotate_right(1) assert isinstance(dl._head, DoublyNode) assert isinstance(dl._tail, DoublyNode) assert dl.to_list() == [6, 1, 2, 3, 4, 5] assert dl._head.get_data() == 6 assert dl._head.get_prev() is None assert dl._tail.get_data() == 5 assert dl._tail.get_next() is None assert dl[4] == 4 dl.rotate_left(3) assert isinstance(rotated._head, DoublyNode) assert isinstance(rotated._tail, DoublyNode) assert dl.to_list() == [3, 4, 5, 6, 1, 2] assert dl._head.get_data() == 3 assert dl._head.get_prev() is None assert dl._tail.get_data() == 2 assert dl._tail.get_next() is None assert dl[-1] == 2
def test_extend_method(helper): lst = helper.get_list() # two Doubly linked lists are empty dllist1 = DoublyLinkedList() dllist1.extend(DoublyLinkedList()) assert dllist1 == DoublyLinkedList() # one linked list is empty dllist1 = DoublyLinkedList([]) dllist2 = DoublyLinkedList(lst) dllist1.extend(dllist2) assert dllist1 == dllist2 assert len(dllist1) == len(lst) dllist2.extend(dllist1) assert len(dllist2) == 2 * len(lst) # two linked lists are NOT empty dllist1 = DoublyLinkedList(lst) dllist2 = DoublyLinkedList(lst) dllist2.extend(dllist1) assert dllist1.to_list() == lst assert dllist2.to_list() == lst + lst assert len(dllist2) == 2 * len(lst) # extend other data type with pytest.raises(TypeError): DoublyLinkedList().extend(LinkedList()) with pytest.raises(TypeError): DoublyLinkedList().extend(helper.get_list()) with pytest.raises(TypeError): DoublyLinkedList().extend(helper.get_value())
def test_relational_operators(helper): # linked lists have just one value assert DoublyLinkedList([3.14]) == DoublyLinkedList([3.14]) assert ( DoublyLinkedList([helper.get_int()]) != DoublyLinkedList([helper.get_float()]) ) assert ( DoublyLinkedList([helper.get_string()]) != DoublyLinkedList([helper.get_int()]) ) assert ( DoublyLinkedList([helper.get_float()]) != DoublyLinkedList([helper.get_list()]) ) assert DoublyLinkedList([2.9999]) < DoublyLinkedList([3]) assert DoublyLinkedList([3.14]) <= DoublyLinkedList([3.14]) assert DoublyLinkedList([3, 2]) > DoublyLinkedList([3]) assert DoublyLinkedList(["3.14"]) >= DoublyLinkedList(["3.14"]) with pytest.raises(TypeError): ( DoublyLinkedList([helper.get_float()]) < DoublyLinkedList([helper.get_string()]) ) with pytest.raises(TypeError): ( DoublyLinkedList([helper.get_value()]) <= DoublyLinkedList([helper.get_list()]) ) with pytest.raises(TypeError): ( DoublyLinkedList([helper.get_string()]) > DoublyLinkedList([helper.get_list()]) ) with pytest.raises(TypeError): ( DoublyLinkedList([helper.get_list()]) >= DoublyLinkedList([helper.get_float()]) ) # linked lists have more than one value dllist1 = DoublyLinkedList([1, "2", 3.14]) dllist2 = DoublyLinkedList([1, "2", 5.14]) assert dllist1 == dllist1 assert dllist1 != dllist2 assert dllist1 < dllist2 assert dllist1 <= dllist2 assert dllist2 > dllist1 assert dllist2 >= dllist1 # slicing lists assert dllist1[:-1] == dllist2[:-1] assert dllist1[-1:] != dllist2[-1:] assert dllist1[:1] < dllist2 assert dllist1[:2] <= dllist2 with pytest.raises(TypeError): assert dllist1[1:] < dllist2 with pytest.raises(TypeError): assert dllist1[1:] <= dllist2 # if the other one isn't a doubly linked list actual_list = [1, "2", 5.14] with pytest.raises(TypeError): assert dllist1 == actual_list with pytest.raises(TypeError): assert dllist1 != actual_list with pytest.raises(TypeError): assert dllist1 < actual_list with pytest.raises(TypeError): assert dllist1 <= actual_list with pytest.raises(TypeError): assert dllist2 > actual_list with pytest.raises(TypeError): assert dllist2 >= actual_list # if the other one is a linked list llist = LinkedList([1, "2", 5.14]) with pytest.raises(TypeError): assert dllist1 == llist with pytest.raises(TypeError): assert dllist1 != llist with pytest.raises(TypeError): assert dllist1 < llist with pytest.raises(TypeError): assert dllist1 <= llist with pytest.raises(TypeError): assert dllist2 > llist with pytest.raises(TypeError): assert dllist2 >= llist
def test_creating_doubly_linked_list_from_constructor(helper): # Using constructor val = helper.get_value() dl = DoublyLinkedList() dl.add_front(val) dl._head.get_data() == dl._tail.get_data() == val dl._head.get_next() == dl._head._next is None dl._head.get_prev() == dl._head._prev is None dl._tail.get_next() == dl._head._next is None dl._tail.get_prev() == dl._head._prev is None assert len(dl) == dl._length == 1 assert dl.to_list() == [item for item in dl] == [val] dl = DoublyLinkedList() with pytest.raises(TypeError): dl.add_end(Node(helper.get_value())) with pytest.raises(TypeError): dl.add_front(Node(helper.get_value())) # Using Node dl = DoublyLinkedList() with pytest.raises(TypeError): dl.add_end(Node(helper.get_value())) with pytest.raises(TypeError): dl.add_front(Node(helper.get_value())) assert len(dl) == dl._length == 0 assert dl.to_list() == [item for item in dl] == [] # Using DoublyNode dl = DoublyLinkedList() with pytest.raises(TypeError): dl.add_end(DoublyNode(helper.get_value())) with pytest.raises(TypeError): dl.add_front(DoublyNode(helper.get_value())) assert len(dl) == dl._length == 0 assert dl.to_list() == [item for item in dl] == []
def test_list_with_random_numbers(helper): # test add_end() and remove_end() lst = helper.get_list(length=100) dl = DoublyLinkedList() for i in lst: dl.add_end(i) assert len(dl) == len(lst) assert dl._head.get_data() == lst[0] assert not dl.is_empty() for _ in range(len(lst)): assert dl[0] == lst[0] lst.pop() dl.remove_end() assert len(dl) == 0 assert dl.is_empty() # test add_front() and remove_front() lst = helper.get_list(length=100) for i in lst: dl.add_front(i) assert len(dl) == len(lst) assert dl._head.get_data() == lst[-1] assert not dl.is_empty() for _ in range(len(lst)): assert dl[0] == lst[-1] lst.pop() dl.remove_front() assert len(dl) == 0 assert dl.is_empty()
def test_list_with_known_values(): dl = DoublyLinkedList() dl.add_front(10) dl.add_front(5) assert dl.to_list() == [5, 10] dl.remove(20) dl.remove_front() dl.remove_end() assert dl == DoublyLinkedList() dl.insert(0, 100) dl.insert(1, 200) dl.insert(1, 100) assert 100 in dl and 200 in dl assert dl == DoublyLinkedList([100, 100, 200]) assert dl.copy().to_list() == [100, 100, 200] assert dl.reverse() == DoublyLinkedList([200, 100, 100]) dl.remove(100) rev = dl.reverse() assert dl == rev dl.clear() assert not rev.is_empty() assert dl.is_empty() # ================================================== dl = DoublyLinkedList() dl.add_front(6) dl.add_end(20) dl.insert(1, 10) dl.insert(2, 77) dl.insert(4, 43) dl.insert(0, 2) assert 43 in dl assert dl[1:4].to_list() == [6, 10, 77] assert dl.copy().to_list() == [2, 6, 10, 77, 20, 43] del dl[len(dl) - 1] assert dl.reverse().to_list() == [20, 77, 10, 6, 2] assert dl._length == len(dl) == 5 dl.clear() assert dl.is_empty()
def test_list_with_same_value(helper): length = helper.get_pos_int() val = helper.get_value() dl = DoublyLinkedList() # test add_end for _ in range(length): dl.add_end(val) # test add_front for _ in range(length): dl.add_front(val) # test __setitem__() dl[1] = val assert dl == dl.reverse() assert dl == dl.copy() assert not dl.is_empty() assert len(dl) == 2 * length assert dl.count(val) == 2 * length assert dl.to_list() == [val] * (2 * length) # test split left_list, right_list = dl.split(length) assert len(left_list) == len(right_list) == length # test clear left_list.clear() right_list.clear() assert len(left_list) == len(right_list) == 0 # test remove for i in range(length): if i > length // 2: dl.remove_end() else: dl.remove_front() assert len(dl) == dl.count(val) == length dl.remove(val, all=True) assert dl.is_empty() assert len(dl) == 0
def test_list_with_one_element(helper): val = helper.get_value() dl = DoublyLinkedList() dl.insert(0, val) assert dl._head.get_data() == val assert dl._tail.get_data() == val assert dl._head.get_next() is None assert dl._head.get_prev() is None assert dl._tail.get_next() is None assert dl._tail.get_prev() is None assert len(dl) == 1 assert not dl.is_empty() assert val in dl assert [item for item in dl] == [val] assert dl.to_list() == [val] assert dl == dl.copy() assert dl == dl.reverse() # ==================== test rotate ==================== assert dl == dl.rotate_left(helper.get_pos_int(), inplace=False) assert dl == dl.rotate_right(helper.get_pos_int(), inplace=False) # ==================== test operators ==================== assert dl != DoublyLinkedList() assert dl > DoublyLinkedList() assert dl >= DoublyLinkedList() assert DoublyLinkedList() < dl assert DoublyLinkedList() <= dl with pytest.raises(TypeError): assert dl != LinkedList() with pytest.raises(TypeError): assert dl > LinkedList() with pytest.raises(TypeError): assert dl >= LinkedList() with pytest.raises(TypeError): assert LinkedList() < dl with pytest.raises(TypeError): assert LinkedList() <= dl # ==================== test add/remove ==================== new_value = helper.get_value() dl.add_front(new_value) dl.remove_front() dl.add_end(new_value) dl.remove_end() tmp_dl = DoublyLinkedList() tmp_dl.add_front(val) assert dl == tmp_dl # ==================== test insert/split ==================== with pytest.raises(IndexError): dl.insert(2, helper.get_value()) with pytest.raises(IndexError): dl.insert(-1, helper.get_value()) with pytest.raises(IndexError): dl.split(helper.get_pos_int(a=2))
def test_empty_doubly_linked_list(helper): EMPTY = "┌─\n│\n└─" # represents empty Doubly LinkedList dl = DoublyLinkedList() assert str(dl) == EMPTY assert dl._length == len(dl) == 0 assert dl.is_empty() assert dl.to_list() == [] assert [_ for _ in dl] == [] assert len(dl.copy()) == 0 assert len(dl.reverse()) == 0 # ==================== test operators ==================== with pytest.raises(TypeError): LinkedList() == DoublyLinkedList() with pytest.raises(TypeError): LinkedList() != DoublyLinkedList() with pytest.raises(TypeError): LinkedList() > DoublyLinkedList() with pytest.raises(TypeError): LinkedList() >= DoublyLinkedList() with pytest.raises(TypeError): LinkedList() < DoublyLinkedList() with pytest.raises(TypeError): LinkedList() <= DoublyLinkedList() assert DoublyLinkedList() == DoublyLinkedList() assert dl == dl.copy() assert dl == dl.reverse() assert DoublyLinkedList() != DoublyLinkedList([helper.get_value()]) assert DoublyLinkedList() < DoublyLinkedList([helper.get_value()]) assert DoublyLinkedList() <= DoublyLinkedList([helper.get_value()]) assert DoublyLinkedList([helper.get_value()]) > DoublyLinkedList() assert DoublyLinkedList([helper.get_value()]) >= DoublyLinkedList() # ==================== test count ==================== assert dl.count(0) == 0 assert dl.count(None) == 0 assert dl.count(Node(helper.get_value())) == 0 assert dl.count(DoublyNode(helper.get_value())) == 0 assert dl.count(helper.get_value()) == 0 # ==================== test __contains__ ==================== assert None not in dl assert Node(helper.get_value()) not in dl assert 0 not in dl assert helper.get_value() not in dl assert LinkedList() not in dl # ==================== test split ==================== left_list, right_list = dl.split(0) assert str(left_list) == str(right_list) == EMPTY with pytest.raises(TypeError): dl.split(helper.get_string()) with pytest.raises(TypeError): dl.split(helper.get_float()) with pytest.raises(TypeError): dl.split(True) with pytest.raises(IndexError): dl.split(-1) with pytest.raises(IndexError): dl.split(helper.get_int()) # ==================== test rotate ==================== assert dl.rotate_left(helper.get_pos_int(), inplace=False) == dl assert dl.rotate_right(helper.get_pos_int(), inplace=False) == dl assert len(dl.rotate_left(helper.get_pos_int(), inplace=False)) == 0 assert len(dl.rotate_right(helper.get_pos_int(), inplace=False)) == 0 with pytest.raises(TypeError): dl.rotate_left(helper.get_string()) with pytest.raises(TypeError): dl.rotate_right(helper.get_float()) with pytest.raises(TypeError): dl.rotate_left([]) with pytest.raises(ValueError): dl.rotate_left(helper.get_neg_int()) with pytest.raises(ValueError): dl.rotate_right(helper.get_neg_int()) # ==================== test remove/del ==================== dl.remove_front() # shouldn't raise any Error dl.remove_end() # shouldn't raise any Error dl.remove(helper.get_value()) dl.remove(helper.get_value(), False) with pytest.raises(TypeError): dl.remove(helper.get_value(), all=helper.get_string()) with pytest.raises(IndexError): del dl[0], dl[helper.get_pos_int()], dl[helper.get_neg_int()] # ==================== test __getitem__ ==================== with pytest.raises(IndexError): _ = dl[0] with pytest.raises(IndexError): _ = dl[helper.get_pos_int()] with pytest.raises(IndexError): _ = dl[helper.get_neg_int()] assert DoublyLinkedList() == dl[0:10] # ==================== test insert/set ==================== with pytest.raises(IndexError): dl.insert(helper.get_pos_int(), helper.get_pos_int()) with pytest.raises(IndexError): dl.insert(helper.get_neg_int(), helper.get_pos_int()) with pytest.raises(IndexError): dl[0] = helper.get_float() with pytest.raises(IndexError): dl[helper.get_int()] = Node(helper.get_float()) with pytest.raises(ValueError): dl.insert(0, None) with pytest.raises(TypeError): dl.insert(0, Node(helper.get_value()))